Вход Регистрация
Файл: library/XenForo/Importer/PhpBb3.php
Строк: 1474
<?php

class XenForo_Importer_PhpBb3 extends XenForo_Importer_Abstract
{
    
/**
     * Source database connection.
     *
     * @var Zend_Db_Adapter_Abstract
     */
    
protected $_sourceDb;

    protected 
$_prefix;

    protected 
$_charset 'utf-8';
    protected 
$_defaultLang 'en';
    protected 
$_defaultLangId 1;

    protected 
$_groupMap null;
    protected 
$_userFieldMap null;

    protected 
$_config;

    public static function 
getName()
    {
        return 
'phpBB 3.0';
    }

    public function 
configure(XenForo_ControllerAdmin_Abstract $controller, array &$config)
    {
        if (
$config)
        {
            
$errors $this->validateConfiguration($config);
            if (
$errors)
            {
                return 
$controller->responseError($errors);
            }

            return 
true;
        }
        else
        {
            
$viewParams = array();
        }

        return 
$controller->responseView('XenForo_ViewAdmin_Import_PhpBb3_Config''import_phpbb3_config'$viewParams);
    }

    public function 
validateConfiguration(array &$config)
    {
        
$errors = array();

        
$config['db']['prefix'] = preg_replace('/[^a-z0-9_]/i'''$config['db']['prefix']);

        try
        {
            
$db Zend_Db::factory('mysqli',
                array(
                    
'host' => $config['db']['host'],
                    
'port' => $config['db']['port'],
                    
'username' => $config['db']['username'],
                    
'password' => $config['db']['password'],
                    
'dbname' => $config['db']['dbname'],
                    
'charset' => 'utf8'
                
)
            );
            
$db->getConnection();
        }
        catch (
Zend_Db_Exception $e)
        {
            
$errors[] = new XenForo_Phrase('source_database_connection_details_not_correct_x', array('error' => $e->getMessage()));
        }

        if (
$errors)
        {
            return 
$errors;
        }

        try
        {
            
$db->query('
                SELECT user_id
                FROM ' 
$config['db']['prefix'] . 'users
                LIMIT 1
            '
);
        }
        catch (
Zend_Db_Exception $e)
        {
            if (
$config['db']['dbname'] === '')
            {
                
$errors[] = new XenForo_Phrase('please_enter_database_name');
            }
            else
            {
                
$errors[] = new XenForo_Phrase('table_prefix_or_database_name_is_not_correct');
            }
        }

        if (!
file_exists($config['attachmentPath']) || !is_dir($config['attachmentPath']))
        {
            
$errors[] = new XenForo_Phrase('attachments_directory_not_found');
        }

        if (!
file_exists($config['avatarPath']) || !is_dir($config['avatarPath']))
        {
            
$errors[] = new XenForo_Phrase('avatars_directory_not_found');
        }

        return 
$errors;
    }

    public function 
getSteps()
    {
        return array(
            
'userGroups' => array(
                
'title' => new XenForo_Phrase('import_user_groups')
            ),
            
'userFields' => array(
                
'title' => new XenForo_Phrase('import_custom_user_fields'),
            ),
            
'users' => array(
                
'title' => new XenForo_Phrase('import_users'),
                
'depends' => array('userGroups''userFields')
            ),
            
'avatars' => array(
                
'title' => new XenForo_Phrase('import_custom_avatars'),
                
'depends' => array('users')
            ),
            
'privateMessages' => array(
                
'title' => new XenForo_Phrase('import_private_messages'),
                
'depends' => array('users')
            ),
            
'forums' => array(
                
'title' => new XenForo_Phrase('import_forums'),
                
'depends' => array('userGroups')
            ),
            
'forumPermissions' => array(
                
'title' => new XenForo_Phrase('import_forum_permissions'),
                
'depends' => array('forums')
            ),
            
'moderators' => array(
                
'title' => new XenForo_Phrase('import_forum_moderators'),
                
'depends' => array('forums''users')
            ),
            
'threads' => array(
                
'title' => new XenForo_Phrase('import_threads_and_posts'),
                
'depends' => array('forums''users')
            ),
            
'polls' => array(
                
'title' => new XenForo_Phrase('import_polls'),
                
'depends' => array('threads')
            ),
            
'attachments' => array(
                
'title' => new XenForo_Phrase('import_attached_files'),
                
'depends' => array('threads')
            ),
        );

        
// TODO: admins and admin permissions, super moderators and permissions, ideally some sort of permission import
    
}

    protected function 
_bootstrap(array $config)
    {
        if (
$this->_sourceDb)
        {
            
// already run
            
return;
        }

        @
set_time_limit(0);

        
$this->_config $config;

        
$this->_sourceDb Zend_Db::factory('mysqli',
            array(
                
'host' => $config['db']['host'],
                
'port' => $config['db']['port'],
                
'username' => $config['db']['username'],
                
'password' => $config['db']['password'],
                
'dbname' => $config['db']['dbname'],
                
'charset' => 'utf8'
            
)
        );

        
$this->_prefix preg_replace('/[^a-z0-9_]/i'''$config['db']['prefix']);

        
$this->_defaultLang $this->_sourceDb->fetchOne("
            SELECT config_value
            FROM " 
$this->_prefix "config
            WHERE config_name = 'default_lang'
        "
);
        
$this->_defaultLangId $this->_sourceDb->fetchOne('
            SELECT lang_id
            FROM ' 
$this->_prefix 'lang
            WHERE lang_iso = ' 
$this->_sourceDb->quote($this->_defaultLang)
        );
    }

    public function 
stepUserGroups($start, array $options)
    {
        
$sDb $this->_sourceDb;
        
$prefix $this->_prefix;

        
/* @var $model XenForo_Model_Import */
        
$model $this->_importModel;

        
$userGroups $sDb->fetchAll('
            SELECT *
            FROM ' 
$prefix 'groups
            ORDER BY group_id
        '
);

        
$total 0;

        
XenForo_Db::beginTransaction();

        foreach (
$userGroups AS $userGroup)
        {
            
$titlePriority 5;

            switch (
$userGroup['group_id'])
            {
                case 
1// guests
                
case 6// bots
                    
$model->logImportData('userGroup'$userGroup['group_id'], XenForo_Model_User::$defaultGuestGroupId);
                    break;

                case 
2// registered users
                
case 3// coppa
                    
$model->logImportData('userGroup'$userGroup['group_id'], XenForo_Model_User::$defaultRegisteredGroupId);
                    break;

                case 
5// admins
                    
$model->logImportData('userGroup'$userGroup['group_id'], XenForo_Model_User::$defaultAdminGroupId);
                    continue;

                case 
4// super mods
                    
$titlePriority 910;
                    
// fall through intentionally

                
default:
                    
$import = array(
                        
'title' => $this->_convertToUtf8($userGroup['group_name'], true),
                        
'display_style_priority' => $titlePriority,
                        
'permissions' => $this->_convertGlobalPermissionsForGroup($userGroup['group_id'])
                    );

                    if (
$model->importUserGroup($userGroup['group_id'], $import))
                    {
                        
$total++;
                    }
            }
        }

        
XenForo_Model::create('XenForo_Model_UserGroup')->rebuildDisplayStyleCache();

        
XenForo_Db::commit();

        
$this->_session->incrementStepImportTotal($total);

        return 
true;
    }

    protected function 
_convertGlobalPermissionsForGroup($groupId)
    {
        
$phpBbPerms $this->_getGroupPermissions($groupId0);
        
$perms = array();

        
// no equivalents
        
$perms['general']['view'] = 'allow';
        
$perms['general']['viewNode'] = 'allow';
        
$perms['general']['followModerationRules'] = 'allow';
        
$perms['general']['report'] = 'allow';
        
$perms['forum']['viewOthers'] = 'allow';
        
$perms['forum']['viewContent'] = 'allow';
        
$perms['forum']['like'] = 'allow';
        
$perms['forum']['votePoll'] = 'allow';
        
$perms['conversation']['receive'] = 'allow';

        
$this->_setXfPermissionBasedOnPermission($perms$phpBbPerms'general''editSignature''u_sig');
        
$this->_setXfPermissionBasedOnPermission($perms$phpBbPerms'general''bypassFloodCheck''u_ignoreflood');
        
$this->_setXfPermissionBasedOnPermission($perms$phpBbPerms'general''bypassUserPrivacy''u_viewonline');
        
$this->_setXfPermissionBasedOnPermission($perms$phpBbPerms'general''viewProfile''u_viewprofile');
        
$this->_setXfPermissionBasedOnPermission($perms$phpBbPerms'general''search''u_search');
        
$this->_setXfPermissionBasedOnPermission($perms$phpBbPerms'forum''uploadAttachment''u_attach');
        
$this->_setXfPermissionBasedOnPermission($perms$phpBbPerms'forum''viewAttachment''u_download');
        
$this->_setXfPermissionBasedOnPermission($perms$phpBbPerms'avatar''allowed''u_chgavatar');
        
$this->_setXfPermissionBasedOnPermission($perms$phpBbPerms'conversation''start''u_sendpm');
        
$this->_setXfPermissionBasedOnPermission($perms$phpBbPerms'conversation''editOwnPost''u_pm_edit');
        if (
$this->_hasPhpBbPerm($phpBbPerms'u_pm_edit'))
        {
            
$perms['conversation']['editOwnPostTimeLimit'] = 5;
        }
        if (
$this->_hasPhpBbPerm($phpBbPerms'u_viewprofile'))
        {
            
$perms['profilePost']['view'] = 'allow';
            
$perms['profilePost']['like'] = 'allow';
            
$perms['profilePost']['manageOwn'] = 'allow';
            
$perms['profilePost']['deleteOwn'] = 'allow';
            
$perms['profilePost']['post'] = 'allow';
            
$perms['profilePost']['comment'] = 'allow';
            
$perms['profilePost']['editOwn'] = 'allow';
        }

        return 
$perms;
    }

    protected function 
_getGroupPermissions($ids$forumId 0)
    {
        
$sDb $this->_sourceDb;
        
$prefix $this->_prefix;

        
$perms = array();

        if (!
is_array($ids))
        {
            
$ids = array($ids);
        }
        if (!
$ids)
        {
            return array();
        }

        
$groupPermsResult $sDb->query('
            SELECT o.auth_option, g.auth_setting
            FROM ' 
$prefix 'acl_groups AS g
            INNER JOIN ' 
$prefix 'acl_options AS o ON (g.auth_option_id = o.auth_option_id)
            WHERE g.group_id IN (' 
$sDb->quote($ids) . ')
                AND g.auth_option_id > 0
                AND g.forum_id = ' 
$sDb->quote($forumId) . '
        '
);
        while (
$perm $groupPermsResult->fetch())
        {
            
$this->_mergePermissions($perms$perm);
        }

        
$rolePermsResult $sDb->query('
            SELECT o.auth_option, r.auth_setting
            FROM ' 
$prefix 'acl_groups AS g
            INNER JOIN ' 
$prefix 'acl_roles_data AS r ON (g.auth_role_id = r.role_id)
            INNER JOIN ' 
$prefix 'acl_options AS o ON (r.auth_option_id = o.auth_option_id)
            WHERE g.group_id IN (' 
$sDb->quote($ids) . ')
                AND g.auth_role_id > 0
                AND g.forum_id = ' 
$sDb->quote($forumId) . '
        '
);
        while (
$perm $rolePermsResult->fetch())
        {
            
$this->_mergePermissions($perms$perm);
        }

        return 
$perms;
    }

    protected function 
_getUserPermissions($id$forumId 0)
    {
        
$sDb $this->_sourceDb;
        
$prefix $this->_prefix;

        
$perms = array();

        
$userPermsResult $sDb->query('
            SELECT o.auth_option, u.auth_setting
            FROM ' 
$prefix 'acl_users AS u
            INNER JOIN ' 
$prefix 'acl_options AS o ON (u.auth_option_id = o.auth_option_id)
            WHERE u.user_id = ' 
$sDb->quote($id) . '
                AND u.auth_option_id > 0
                AND u.forum_id = ' 
$sDb->quote($forumId) . '
        '
);
        while (
$perm $userPermsResult->fetch())
        {
            
$this->_mergePermissions($perms$perm);
        }

        
$rolePermsResult $sDb->query('
            SELECT o.auth_option, r.auth_setting
            FROM ' 
$prefix 'acl_users AS u
            INNER JOIN ' 
$prefix 'acl_roles_data AS r ON (u.auth_role_id = r.role_id)
            INNER JOIN ' 
$prefix 'acl_options AS o ON (r.auth_option_id = o.auth_option_id)
            WHERE u.user_id = ' 
$sDb->quote($id) . '
                AND u.auth_role_id > 0
                AND u.forum_id = ' 
$sDb->quote($forumId) . '
        '
);
        while (
$perm $rolePermsResult->fetch())
        {
            
$this->_mergePermissions($perms$perm);
        }

        
$groups $sDb->fetchCol('
            SELECT group_id
            FROM ' 
$prefix 'user_group
            WHERE user_id = ' 
$sDb->quote($id)
        );
        
$groupPerms $this->_getGroupPermissions($groups$forumId);
        foreach (
$groupPerms AS $permId => $permSetting)
        {
            
$perm = array('auth_option' => $permId'auth_setting' => $permSetting);
            
$this->_mergePermissions($perms$perm);
        }

        return 
$perms;
    }

    protected function 
_mergePermissions(array &$perms, array $perm)
    {
        if (!isset(
$perms[$perm['auth_option']]))
        {
            
$perms[$perm['auth_option']] = intval($perm['auth_setting']);
        }
        else if (
$perms[$perm['auth_option']] == || $perm['auth_option'] == 0)
        {
            
$perms[$perm['auth_option']] = 0;
        }
        else if (
$perm['auth_option'] == 1)
        {
            
$perms[$perm['auth_option']] = 1;
        }
        else
        {
            
$perms[$perm['auth_option']] = -1;
        }
    }

    protected function 
_hasPhpBbPerm(array $phpBbPerms$perm)
    {
        return (isset(
$phpBbPerms[$perm]) && $phpBbPerms[$perm] == 1);
    }

    protected function 
_setXfPermissionBasedOnPermission(array &$outputPerms, array $phpBbPerms$xfPermGroup$xfPerm$phpBbPerm$allow 'allow')
    {
        if (!isset(
$phpBbPerms[$phpBbPerm]) || $phpBbPerms[$phpBbPerm] == -1)
        {
            return;
        }

        if (
$phpBbPerms[$phpBbPerm] == 0)
        {
            
$outputPerms[$xfPermGroup][$xfPerm] = 'deny';
        }
        else if (
$phpBbPerms[$phpBbPerm] == 1)
        {
            
$outputPerms[$xfPermGroup][$xfPerm] = $allow;
        }
    }

    public function 
stepUserFields($start, array $options)
    {
        
$sDb $this->_sourceDb;
        
$prefix $this->_prefix;

        
/* @var $model XenForo_Model_Import */
        
$model $this->_importModel;

        
$profileFields $sDb->fetchAll('
            SELECT pf.*, pl.*
            FROM ' 
$prefix 'profile_fields AS pf
            INNER JOIN ' 
$prefix 'profile_lang AS pl ON
                (pf.field_id = pl.field_id AND pl.lang_id = ' 
$sDb->quote($this->_defaultLangId) . ')
        '
);

        
$profileFieldOptions = array();
        
$pfoResult $sDb->query('
            SELECT *
            FROM ' 
$prefix 'profile_fields_lang
            WHERE lang_id = ' 
$sDb->quote($this->_defaultLangId)
        );
        while (
$pfo $pfoResult->fetch())
        {
            
$profileFieldOptions[$pfo['field_id']][$pfo['option_id']] = $this->_convertToUtf8($pfo['lang_value'], true);
        }

        
$existingFields XenForo_Model::create('XenForo_Model_UserField')->getUserFields();

        
$userFieldLookups = array();
        
$total 0;

        
XenForo_Db::beginTransaction($this->_db);

        foreach (
$profileFields AS $profileField)
        {
            
$title $this->_convertToUtf8($profileField['lang_name'], true);
            
$description $this->_convertToUtf8($profileField['lang_explain'], true);

            
$fieldId $model->getUniqueFieldId(
                
str_replace('-''_'XenForo_Link::getTitleForUrl($profileField['field_name'], true)),
                
$existingFields,
                
25
            
);

            
$import = array(
                
'field_id' => $fieldId,
                
'title' => $title,
                
'description' => $description,
                
'display_order' => $profileField['field_order'],
                
'max_length' => $profileField['field_maxlen'],
                
'viewable_profile' => !$profileField['field_no_view'],
                
'user_editable' => $profileField['field_show_profile'] ? 'yes' 'never',
                
'viewable_message' => (isset($profileField['field_show_on_vt']) ? (bool)$profileField['field_show_on_vt'] : 0),
                
'show_registration' => (bool)$profileField['field_show_on_reg'],
                
'required' => (bool)$profileField['field_required']
            );

            if (
$profileField['field_validation'] && $profileField['field_validation'] != '.*')
            {
                
$import['match_type'] = 'regex';
                
$import['match_regex'] = '^' $this->_convertToUtf8($profileField['field_validation']) . '$';
            }

            switch (
$profileField['field_type'])
            {
                case 
1// numbers
                    
$import['field_type'] = 'textbox';
                    
$import['match_type'] = 'number';
                    break;

                case 
2// text box
                    
$import['field_type'] = 'textbox';
                    break;

                case 
3// text area
                    
$import['field_type'] = 'textarea';
                    break;

                case 
4// boolean
                
case 5// drop down
                    
$import['field_type'] = ($profileField['field_type'] == 'radio' 'select');
                    if (empty(
$profileFieldOptions[$profileField['field_id']]))
                    {
                        continue;
                    }
                    
$import['field_choices'] = $profileFieldOptions[$profileField['field_id']];
                    
$userFieldLookups[$profileField['field_name']] = $profileFieldOptions[$profileField['field_id']];
                    break;

                case 
6// date
                    
$import['field_type'] = 'textbox';
                    break;

                default:
                    
$import['field_type'] = 'textbox';
                    break;
            }

            if (
$imported $model->importUserField($profileField['field_name'], $import))
            {
                
$total++;
            }
        }

        
XenForo_Db::commit($this->_db);

        
$this->_session->setExtraData('userFieldLookups'$userFieldLookups);
        
$this->_session->incrementStepImportTotal($total);

        return 
true;
    }

    public function 
configStepUsers(array $options)
    {
        if (
$options)
        {
            return 
false;
        }

        return 
$this->_controller->responseView('XenForo_ViewAdmin_Import_PhpBb3_ConfigUsers''import_config_users');
    }

    public function 
stepUsers($start, array $options)
    {
        
$options array_merge(array(
            
'limit' => 100,
            
'max' => false,
            
// all checkbox options must default to false as they may not be submitted
            
'mergeEmail' => false,
            
'mergeName' => false,
            
'gravatar' => false
        
), $options);

        if (
$options['gravatar'])
        {
            
$options['limit'] = max(5floor($options['limit'] / 2));
        }

        
$sDb $this->_sourceDb;
        
$prefix $this->_prefix;

        
/* @var $model XenForo_Model_Import */
        
$model $this->_importModel;

        if (
$options['max'] === false)
        {
            
$options['max'] = $sDb->fetchOne('
                SELECT MAX(user_id)
                FROM ' 
$prefix 'users
            '
);
        }

        
$users $sDb->fetchAll(
            
$sDb->limit($this->_getSelectUserSql('users.user_id > ' $sDb->quote($start)), $options['limit'])
        );
        if (!
$users)
        {
            return 
$this->_getNextUserStep();
        }

        
XenForo_Db::beginTransaction();

        
$next 0;
        
$total 0;
        foreach (
$users AS $user)
        {
            
$next $user['user_id'];

            
$imported $this->_importOrMergeUser($user$options);
            if (
$imported)
            {
                
$total++;
            }
        }

        
XenForo_Db::commit();

        
$this->_session->incrementStepImportTotal($total);

        return array(
$next$options$this->_getProgressOutput($next$options['max']));
    }

    public function 
stepUsersMerge($start, array $options)
    {
        
$sDb $this->_sourceDb;

        
$manual $this->_session->getExtraData('userMerge');

        if (
$manual)
        {
            
$merge $sDb->fetchAll($this->_getSelectUserSql('users.user_id IN (' $sDb->quote(array_keys($manual)) . ')'));

            
$resolve $this->_controller->getInput()->filterSingle('resolve'XenForo_Input::ARRAY_SIMPLE);
            if (
$resolve && !empty($options['shownForm']))
            {
                
$this->_session->unsetExtraData('userMerge');
                
$this->_resolveUserConflicts($merge$resolve);
            }
            else
            {
                
// prevents infinite loop if redirected back to step
                
$options['shownForm'] = true;
                
$this->_session->setStepInfo(0$options);

                
$users = array();
                foreach (
$merge AS $user)
                {
                    
$users[$user['user_id']] = array(
                        
'username' => $this->_convertToUtf8($user['username'], true),
                        
'email' => $this->_convertToUtf8($user['user_email'], true),
                        
'message_count' => $user['user_posts'],
                        
'register_date' => $user['user_regdate'],
                        
'conflict' => $manual[$user['user_id']]
                    );
                }

                return 
$this->_controller->responseView(
                    
'XenForo_ViewAdmin_Import_MergeUsers''import_merge_users', array('users' => $users)
                );
            }
        }

        return 
$this->_getNextUserStep();
    }

    public function 
stepUsersFailed($start, array $options)
    {
        
$sDb $this->_sourceDb;

        
$manual $this->_session->getExtraData('userFailed');

        if (
$manual)
        {
            
$users $this->_sourceDb->fetchAll($this->_getSelectUserSql('users.user_id IN (' $sDb->quote(array_keys($manual)) . ')'));

            
$resolve $this->_controller->getInput()->filterSingle('resolve'XenForo_Input::ARRAY_SIMPLE);
            if (
$resolve && !empty($options['shownForm']))
            {
                
$this->_session->unsetExtraData('userFailed');
                
$this->_resolveUserConflicts($users$resolve);
            }
            else
            {
                
// prevents infinite loop if redirected back to step
                
$options['shownForm'] = true;
                
$this->_session->setStepInfo(0$options);

                
$failedUsers = array();
                foreach (
$users AS $user)
                {
                    
$failedUsers[$user['user_id']] = array(
                        
'username' => $this->_convertToUtf8($user['username'], true),
                        
'email' => $this->_convertToUtf8($user['user_email'], true),
                        
'message_count' => $user['user_posts'],
                        
'register_date' => $user['user_regdate'],
                        
'failure' => $manual[$user['user_id']]
                    );
                }

                return 
$this->_controller->responseView(
                    
'XenForo_ViewAdmin_Import_FailedUsers''import_failed_users', array('users' => $failedUsers)
                );
            }
        }

        return 
$this->_getNextUserStep();
    }

    protected function 
_resolveUserConflicts(array $users, array $resolve)
    {
        
/* @var $model XenForo_Model_Import */
        
$model $this->_importModel;

        
$total 0;

        
XenForo_Db::beginTransaction();

        foreach (
$users AS $user)
        {
            if (empty(
$resolve[$user['user_id']]))
            {
                continue;
            }

            
$info $resolve[$user['user_id']];

            if (empty(
$info['action']) || $info['action'] == 'change')
            {
                if (isset(
$info['email']))
                {
                    
$user['user_email'] = $info['email'];
                }
                if (isset(
$info['username']))
                {
                    
$user['username'] = $info['username'];
                }

                
$imported $this->_importOrMergeUser($user);
                if (
$imported)
                {
                    
$total++;
                }
            }
            else if (
$info['action'] == 'merge')
            {
                
$im $this->_importModel;

                if (
$match $im->getUserIdByEmail($this->_convertToUtf8($user['user_email'], true)))
                {
                    
$this->_mergeUser($user$match);
                }
                else if (
$match $im->getUserIdByUserName($this->_convertToUtf8($user['username'], true)))
                {
                    
$this->_mergeUser($user$match);
                }

                
$total++;
            }
        }

        
XenForo_Db::commit();

        
$this->_session->incrementStepImportTotal($total'users');
    }

    protected function 
_getNextUserStep()
    {
        if (
$this->_session->getExtraData('userMerge'))
        {
            return 
'usersMerge';
        }

        if (
$this->_session->getExtraData('userFailed'))
        {
            return 
'usersFailed';
        }

        return 
true;
    }

    protected function 
_importOrMergeUser(array $user, array $options = array())
    {
        
$im $this->_importModel;

        if (
$user['user_email'] && $emailMatch $im->getUserIdByEmail($this->_convertToUtf8($user['user_email'], true)))
        {
            if (!empty(
$options['mergeEmail']))
            {
                return 
$this->_mergeUser($user$emailMatch);
            }
            else
            {
                if (
$im->getUserIdByUserName($this->_convertToUtf8($user['username'], true)))
                {
                    
$this->_session->setExtraData('userMerge'$user['user_id'], 'both');
                }
                else
                {
                    
$this->_session->setExtraData('userMerge'$user['user_id'], 'email');
                }
                return 
false;
            }
        }

        
$name utf8_substr($this->_convertToUtf8(trim($user['username']), true), 050);

        if (
$nameMatch $im->getUserIdByUserName($name))
        {
            if (!empty(
$options['mergeName']))
            {
                return 
$this->_mergeUser($user$nameMatch);
            }
            else
            {
                
$this->_session->setExtraData('userMerge'$user['user_id'], 'name');
                return 
false;
            }
        }

        return 
$this->_importUser($user$options);
    }

    protected 
$_userActivationSetting null;

    protected function 
_importUser(array $user, array $options)
    {
        
$sDb $this->_sourceDb;
        
$prefix $this->_prefix;

        
/* @var $model XenForo_Model_Import */
        
$model $this->_importModel;

        if (
$this->_groupMap === null)
        {
            
$this->_groupMap $this->_importModel->getImportContentMap('userGroup');
        }

        if (
$this->_userFieldMap === null)
        {
            
$this->_userFieldMap $this->_importModel->getImportContentMap('userField');
        }

        if (
$this->_userActivationSetting === null)
        {
            
$this->_userActivationSetting $sDb->fetchOne('
                SELECT config_value
                FROM ' 
$prefix 'config
                WHERE config_name = '
require_activation'
            '
);
        }

        if (
$user['user_type'] == 2)
        {
            return 
false// ignore this user
        
}

        
$groups $sDb->fetchCol('
            SELECT group_id
            FROM ' 
$prefix 'user_group
            WHERE user_id = ' 
$sDb->quote($user['user_id']) . '
                AND group_id <> ' 
$sDb->quote($user['group_id']) . '
                AND user_pending = 0
        '
);

        
$user['user_options'] = intval($user['user_options']);

        
$import = array(
            
'username' => $this->_convertToUtf8($user['username'], true),
            
'email' => $this->_convertToUtf8($user['user_email'], true),
            
'user_group_id' => $this->_mapLookUp($this->_groupMap$user['group_id'], XenForo_Model_User::$defaultRegisteredGroupId),
            
'secondary_group_ids' => $this->_mapLookUpList($this->_groupMap$groups),
            
'authentication' => array(
                
'scheme_class' => 'XenForo_Authentication_PhpBb3',
                
'data' => array(
                    
'hash' => $user['user_password']
                )
            ),
            
'last_activity' => $user['user_lastvisit'],
            
'register_date' => $user['user_regdate'],
            
'ip' => $user['user_ip'],
            
'homepage' => $this->_convertToUtf8($user['user_website'], true),
            
'message_count' => $user['user_posts'],
            
'is_admin' => ($user['user_type'] == 0), // founders get all admin permissions
            
'is_banned' => ($user['ban_id'] ? 0),
            
'signature' => $this->_sanitizeBbCode($user['user_sig']),
            
'timezone' => $this->_importModel->resolveTimeZoneOffset($user['user_timezone'], $user['user_dst']),
            
'visible' => $user['user_allow_viewonline'],
            
'content_show_signature' => (($user['user_options'] & << 3) ? 0), // view sigs
            
'receive_admin_email' => $user['user_allow_massemail'],
            
'default_watch_state' => ($user['user_notify'] ? 'watch_email' ''),
            
'allow_send_personal_conversation' => ($user['user_allow_pm'] ? 'everyone' 'none'),
            
'email_on_conversation' => $user['user_notify_pm']
        );

        if (
$user['group_id'] == 3// coppa
        
{
            
$import['user_state'] = 'moderated';
        }
        else if (
$user['user_type'] == && $user['user_inactive_reason'] == 1// inactive at registration
        
{
            
$input['user_state'] = ($this->_userActivationSetting == 'moderated' 'email_confirm');
        }
        else if (
$user['user_type'] == && $user['user_inactive_reason'] == 2// inactive at profile edit
        
{
            
$input['user_state'] = 'email_confirm_edit';
        }
        else
        {
            
$import['user_state'] = 'valid';
        }

        if (
$user['user_birthday'])
        {
            
$parts explode('-'$user['user_birthday']);
            if (
count($parts) == 3)
            {
                
$import['dob_day'] = trim($parts[0]);
                
$import['dob_month'] = trim($parts[1]);
                
$import['dob_year'] = trim($parts[2]);
            }
        }

        
// try to give users without an avatar that have actually posted a gravatar
        
if (!empty($options['gravatar']))
        {
            
// 1 = uploaded avatar
            
if ($user['user_avatar_type'] != && $user['user_email'] && $user['user_lastpost_time']
                && 
XenForo_Model_Avatar::gravatarExists($user['user_email'])
            )
            {
                
$import['gravatar'] = $import['email'];
            }
        }

        
$import['about'] = $this->_convertToUtf8($user['user_interests'], true);
        
$import['location'] = $this->_convertToUtf8($user['user_from'], true);
        
$import['occupation'] = $this->_convertToUtf8($user['user_occ'], true);

        
// custom user fields
        
$userFieldDefinitions $this->_importModel->getUserFieldDefinitions();

        
$identityMap = array(
            
'icq' => 'user_icq',
            
'aim' => 'user_aim',
            
'yahoo' => 'user_yim',
            
'msn' => 'user_msnm'
        
);

        foreach (
$identityMap AS $identityType => $phpBbField)
        {
            if (isset(
$userFieldDefinitions[$identityType]))
            {
                
$import[XenForo_Model_Import::USER_FIELD_KEY][$identityType] = $this->_convertToUtf8($user[$phpBbField], true);
            }
        }

        
$userFieldLookups $this->_session->getExtraData('userFieldLookups');

        foreach (
$this->_userFieldMap AS $oldFieldId => $newFieldId)
        {
            if (!isset(
$userFieldDefinitions[$newFieldId]))
            {
                continue;
            }

            
$userFieldValue '';

            if (isset(
$user["pf_$oldFieldId"]) && $user["pf_$oldFieldId"] !== '')
            {
                if (isset(
$userFieldLookups[$oldFieldId]))
                {
                    
$fieldInfo $userFieldLookups[$oldFieldId];
                    
$fieldChoiceId max(0$user["pf_$oldFieldId"] - 1); // option ids are 0 keyed, values are 1 keyed

                    
if (isset($fieldInfo['choices'][$fieldChoiceId]))
                    {
                        
$userFieldValue $fieldInfo['choices'][$fieldChoiceId];
                    }
                }
                else
                {
                    
// set the field value directly
                    
$userFieldValue $this->_convertToUtf8($user["pf_$oldFieldId"], true);
                }
            }

            
$import[XenForo_Model_Import::USER_FIELD_KEY][$newFieldId] = $userFieldValue;
        }

        if (
$import['is_admin'])
        {
            
// give all admin permissions
            
$adminPerms XenForo_Model::create('XenForo_Model_Admin')->getAllAdminPermissions();
            
$import['admin_permissions'] =  array_keys($adminPerms);
        }

        
$importedUserId $this->_importModel->importUser($user['user_id'], $import$failedKey);
        if (
$importedUserId)
        {
            if (
$user['ban_id'])
            {
                
$this->_importModel->importBan(array(
                    
'user_id' => $importedUserId,
                    
'ban_user_id' => 0,
                    
'ban_date' => $user['ban_start'],
                    
'end_date' => $user['ban_end'],
                    
'user_reason' => $this->_convertToUtf8($user['ban_give_reason'], true)
                ));
            }

            
// TODO: this doesn't necessarily work, as the users may not be imported yet.
            // It could work with maintained user IDs though.
            
$friends = array();
            
$foes = array();
            
$zebraResults $sDb->query('
                SELECT zebra_id, friend, foe
                FROM ' 
$prefix 'zebra
                WHERE user_id = ' 
$sDb->quote($user['user_id'])
            );
            while (
$zebra $zebraResults->fetch())
            {
                if (
$zebra['foe'])
                {
                    
$foes[] = $zebra['zebra_id'];
                }
                if (
$zebra['friend'])
                {
                    
$friends[] = $zebra['zebra_id'];
                }
            }
            if (
$friends)
            {
                
$friends $this->_importModel->getImportContentMap('user'$friends);
                
$this->_importModel->importFollowing($importedUserId$friends);
            }
            if (
$foes)
            {
                
$foes $this->_importModel->getImportContentMap('user'$foes);
                
$this->_importModel->importIgnored($importedUserId$foes);
            }
        }
        else if (
$failedKey)
        {
            
$this->_session->setExtraData('userFailed'$user['user_id'], $failedKey);
        }

        return 
$importedUserId;
    }

    protected function 
_getSelectUserSql($where)
    {
        return 
'
            SELECT users.*, pfd.*, ban.*, users.user_id
            FROM ' 
$this->_prefix 'users AS users
            LEFT JOIN ' 
$this->_prefix 'profile_fields_data AS pfd ON
                (pfd.user_id = users.user_id)
            LEFT JOIN ' 
$this->_prefix 'banlist AS ban ON
                (ban.ban_userid = users.user_id AND (ban.ban_end = 0 OR ban.ban_end > ' 
XenForo_Application::$time '))
            WHERE ' 
$where '
                AND users.user_type <> 2
            ORDER BY users.user_id
        '
;
    }

    protected function 
_mergeUser(array $user$targetUserId)
    {
        
$this->_db->query('
            UPDATE xf_user SET
                message_count = message_count + ?,
                register_date = IF(register_date > ?, ?, register_date)
            WHERE user_id = ?
        '
, array($user['user_posts'], $user['user_regdate'], $user['user_regdate'], $targetUserId));

        
$this->_importModel->logImportData('user'$user['user_id'], $targetUserId);

        return 
$targetUserId;
    }

    public function 
stepAvatars($start, array $options)
    {
        
$options array_merge(array(
            
'path' => isset($this->_config['avatarPath']) ? $this->_config['avatarPath'] : '',
            
'limit' => 50,
            
'max' => false
        
), $options);

        
$sDb $this->_sourceDb;
        
$prefix $this->_prefix;

        
/* @var $model XenForo_Model_Import */
        
$model $this->_importModel;

        if (
$options['max'] === false)
        {
            
$options['max'] = $sDb->fetchOne('
                SELECT MAX(user_id)
                FROM ' 
$prefix 'users
                WHERE user_avatar_type = 1
            '
);
        }

        
$avatars $sDb->fetchAll($sDb->limit(
            
'
                SELECT *
                FROM ' 
$prefix 'users
                WHERE user_id > ' 
$sDb->quote($start) . '
                    AND user_avatar_type = 1
                ORDER BY user_id
            '
$options['limit']
        ));
        if (!
$avatars)
        {
            return 
true;
        }

        
$avatarSalt $sDb->fetchOne('
            SELECT config_value
            FROM ' 
$prefix 'config
            WHERE config_name = '
avatar_salt'
        '
);

        
$userIdMap $model->getUserIdsMapFromArray($avatars'user_id');

        
$next 0;
        
$total 0;

        foreach (
$avatars AS $avatar)
        {
            
$next $avatar['user_id'];

            
$newUserId $this->_mapLookUp($userIdMap$avatar['user_id']);
            if (!
$newUserId)
            {
                continue;
            }

            
$userId intval($avatar['user_avatar']);
            
$ext substr(strrchr($avatar['user_avatar'], '.'), 1);

            
$avatarFileOrig "$options[path]/{$avatarSalt}_$userId.$ext";
            if (!
file_exists($avatarFileOrig))
            {
                continue;
            }

            
$avatarFile tempnam(XenForo_Helper_File::getTempDir(), 'xf');
            
copy($avatarFileOrig$avatarFile);

            if (
$this->_importModel->importAvatar($avatar['user_id'], $newUserId$avatarFile))
            {
                
$total++;
            }

            @
unlink($avatarFile);
        }

        
$this->_session->incrementStepImportTotal($total);

        return array(
$next$options$this->_getProgressOutput($next$options['max']));
    }

    public function 
stepPrivateMessages($start, array $options)
    {
        
$options array_merge(array(
            
'limit' => 300,
            
'max' => false
        
), $options);

        
$sDb $this->_sourceDb;
        
$prefix $this->_prefix;

        
/* @var $model XenForo_Model_Import */
        
$model $this->_importModel;

        if (
$options['max'] === false)
        {
            
$options['max'] = $sDb->fetchOne('
                SELECT MAX(msg_id)
                FROM ' 
$prefix 'privmsgs
            '
);
        }

        
$pmTexts $sDb->fetchAll($sDb->limit(
            
'
                SELECT pms.*, users.username
                FROM ' 
$prefix 'privmsgs AS pms
                LEFT JOIN ' 
$prefix 'users AS users ON (pms.author_id = users.user_id)
                WHERE pms.msg_id > ' 
$sDb->quote($start) . '
                ORDER BY pms.msg_id
            '
$options['limit']
        ));
        if (!
$pmTexts)
        {
            return 
true;
        }

        
$next 0;
        
$total 0;

        
XenForo_Db::beginTransaction();

        foreach (
$pmTexts AS $pmText)
        {
            
$next $pmText['msg_id'];

            
$toUserIds = array();
            if (
preg_match_all('#u_(d+)#'$pmText['to_address'], $matches))
            {
                
$toUserIds $matches[1];
            }
            if (!
$toUserIds)
            {
                continue;
            }
            
$toUsers $sDb->fetchPairs('
                SELECT user_id, username
                FROM ' 
$prefix 'users
                WHERE user_id IN (' 
$sDb->quote($toUserIds) . ')
            '
);
            if (!
$toUsers)
            {
                continue;
            }

            
$users = array(
                
$pmText['author_id'] => $pmText['username']
            ) + 
$toUsers;

            
$mapUserIds $model->getImportContentMap('user'array_keys($users));

            
$newFromUserId $this->_mapLookUp($mapUserIds$pmText['author_id']);
            if (!
$newFromUserId)
            {
                continue;
            }

            
$unreadState $sDb->fetchPairs('
                SELECT user_id, MIN(IF(folder_id < 0, 0, pm_unread))
                FROM ' 
$prefix 'privmsgs_to
                WHERE msg_id = ' 
$sDb->quote($pmText['msg_id']) . '
                    AND pm_deleted = 0
                GROUP BY user_id
            '
);

            
$recipients = array();
            foreach (
$users AS $userId => $username)
            {
                
$newUserId $this->_mapLookUp($mapUserIds$userId);
                if (!
$newUserId)
                {
                    continue;
                }

                if (isset(
$unreadState[$userId]))
                {
                    
$lastReadDate = ($unreadState[$userId] ? $pmText['message_time']);
                    
$deleted false;
                }
                else
                {
                    
$lastReadDate $pmText['message_time'];
                    
$deleted true;
                }

                
$recipients[$newUserId] = array(
                    
'username' => $this->_convertToUtf8($usernametrue),
                    
'last_read_date' => $lastReadDate,
                    
'recipient_state' => ($deleted 'deleted' 'active')
                );
            }

            
$fromUserName $this->_convertToUtf8($pmText['username'], true);

            
$conversation = array(
                
'title' => $this->_convertToUtf8($pmText['message_subject'], true),
                
'user_id' => $newFromUserId,
                
'username' => $fromUserName,
                
'start_date' => $pmText['message_time'],
                
'open_invite' => 0,
                
'conversation_open' => 1
            
);

            
$messages = array(
                array(
                    
'message_date' => $pmText['message_time'],
                    
'user_id' => $newFromUserId,
                    
'username' => $fromUserName,
                    
'message' => $this->_sanitizeBbCode($pmText['message_text'])
                )
            );

            if (
$model->importConversation($pmText['msg_id'], $conversation$recipients$messages))
            {
                
$total++;
            }
        }

        
XenForo_Db::commit();

        
$this->_session->incrementStepImportTotal($total);

        return array(
$next$options$this->_getProgressOutput($next$options['max']));
    }

    public function 
stepForums($start, array $options)
    {
        
$sDb $this->_sourceDb;
        
$prefix $this->_prefix;

        
/* @var $model XenForo_Model_Import */
        
$model $this->_importModel;

        if (
$start 0)
        {
            
// after importing everything, rebuild the full permission cache so forums appear
            
XenForo_Model::create('XenForo_Model_Node')->updateNestedSetInfo();
            
XenForo_Model::create('XenForo_Model_Permission')->rebuildPermissionCache();
            return 
true;
        }

        
$forums $sDb->fetchAll('
            SELECT *
            FROM ' 
$prefix 'forums
        '
);
        if (!
$forums)
        {
            return 
true;
        }

        
$forumTree = array();
        foreach (
$forums AS $forum)
        {
            
$forumTree[$forum['parent_id']][$forum['forum_id']] = $forum;
        }

        
XenForo_Db::beginTransaction();

        
$total $this->_importForumTree(0$forumTree);

        
XenForo_Db::commit();

        
$this->_session->incrementStepImportTotal($total);

        return array(
1, array(), '');
    }

    protected function 
_importForumTree($parentId, array $forumTree, array $forumIdMap = array())
    {
        if (!isset(
$forumTree[$parentId]))
        {
            return 
0;
        }

        
XenForo_Db::beginTransaction();

        
$total 0;

        foreach (
$forumTree[$parentId] AS $forum)
        {
            
$import = array(
                
'title' => $this->_convertToUtf8($forum['forum_name'], true),
                
'description' => $this->_sanitizeBbCode($forum['forum_desc'], nulltrue),
                
'display_order' => $forum['left_id'],
                
'parent_node_id' => $this->_mapLookUp($forumIdMap$forum['parent_id'], 0),
                
'display_in_list' => 1
            
);

            if (
$forum['forum_type'] == 2)
            {
                
$import['node_type_id'] = 'LinkForum';
                
$import['link_url'] = $forum['forum_link'];

                
$nodeId $this->_importModel->importLinkForum($forum['forum_id'], $import);
            }
            else if (
$forum['forum_type'] == 1)
            {
                
$import['node_type_id'] = 'Forum';
                
$import['discussion_count'] = $forum['forum_topics'];
                
$import['message_count'] = $forum['forum_posts'];
                
$import['last_post_date'] = $forum['forum_last_post_time'];
                
$import['last_post_username'] = $this->_convertToUtf8($forum['forum_last_poster_name'], true);
                
$import['last_thread_title'] = $this->_convertToUtf8($forum['forum_last_post_subject'], true);

                
$nodeId $this->_importModel->importForum($forum['forum_id'], $import);
            }
            else
            {
                
$import['node_type_id'] = 'Category';

                
$nodeId $this->_importModel->importCategory($forum['forum_id'], $import);
            }

            if (
$nodeId)
            {
                
$forumIdMap[$forum['forum_id']] = $nodeId;

                
$total++;
                
$total += $this->_importForumTree($forum['forum_id'], $forumTree$forumIdMap);
            }
        }

        
XenForo_Db::commit();

        return 
$total;
    }

    public function 
configStepForumPermissions(array $options)
    {
        if (
$options)
        {
            return 
false;
        }

        
$this->_bootstrap($this->_session->getConfig());

        
$nodeMap $this->_importModel->getImportContentMap('node');
        
$forumStates $this->_guessForumPermissions($nodeMap);

        
/* @var $nodeModel XenForo_Model_Node */
        
$nodeModel $this->_importModel->getModelFromCache('XenForo_Model_Node');

        
$nodes $nodeModel->getAllNodes();

        
$displayNodes = array();

        foreach (
$nodes AS $nodeId => $node)
        {
            if (
in_array($nodeId$nodeMap))
            {
                
$node['permissionState'] = $forumStates[$nodeId];

                
$displayNodes[$nodeId] = $node;
            }
        }

        
$viewParams = array('nodes' => $displayNodes);

        return 
$this->_controller->responseView(
            
'XenForo_ViewAdmin_Import_PhpBb3_ConfigForumPermissions',
            
'import_phpbb3_config_forumpermissions',
            
$viewParams
        
);
    }

    protected function 
_guessForumPermissions(array $nodeMap)
    {
        
$sDb $this->_sourceDb;
        
$prefix $this->_prefix;

        
/* @var $model XenForo_Model_Import */
        
$model $this->_importModel;

        
$forumPermissions = array();

        
$forumIds $sDb->fetchCol('
            SELECT forum_id
            FROM ' 
$prefix 'forums
        '
);
        foreach (
$forumIds AS $forumId)
        {
            
$newForumId $this->_mapLookUp($nodeMap$forumId);
            if (!
$newForumId)
            {
                continue;
            }

            
$guestPermissions $this->_getGroupPermissions(1$forumId);
            if (
$this->_hasPhpBbPerm($guestPermissions'f_list'))
            {
                
$state 'public';
            }
            else
            {
                
$userPermissions $this->_getGroupPermissions(2$forumId);
                if (
$this->_hasPhpBbPerm($userPermissions'f_list'))
                {
                    
$state 'memberOnly';
                }
                else
                {
                    
$state 'staffOnly';
                }
            }

            
$forumPermissions[$newForumId] = $state;
        }

        return 
$forumPermissions;
    }

    public function 
stepForumPermissions($start, array $options)
    {
        
/* @var $model XenForo_Model_Import */
        
$model $this->_importModel;

        if (
$start 0)
        {
            
//rebuild the full permission cache so forums appear
            
XenForo_Model::create('XenForo_Model_Permission')->rebuildPermissionCache();

            return 
true;
        }

        
$reset = array('general' => array('viewNode' => 'reset'));
        
$allow = array('general' => array('viewNode' => 'content_allow'));

        
$total 0;

        
XenForo_Db::beginTransaction();

        foreach (
$options AS $nodeId => $permission)
        {
            switch (
$permission)
            {
                case 
'memberOnly':
                {
                    
// revoke view permissions for guests (1)
                    
$model->insertNodePermissionEntries($nodeId10$reset);

                    
$total++;

                    break;
                }

                case 
'staffOnly':
                {
                    
// revoke view permissions for all but staff
                    
$model->insertNodePermissionEntries($nodeId00$reset);

                    
// allow 'Administrating' group (3)
                    
$model->insertNodePermissionEntries($nodeId30$allow);

                    
// allow 'Moderating' group (4)
                    
$model->insertNodePermissionEntries($nodeId40$allow);

                    
$total++;

                    break;
                }

                case 
'public':
                default:
                    
// no change required
            
}
        }

        
XenForo_Db::commit();

        
$this->_session->incrementStepImportTotal($total);

        return array(
1, array(), '');
    }

    public function 
stepModerators($start, array $options)
    {
        
$sDb $this->_sourceDb;
        
$prefix $this->_prefix;

        
/* @var $model XenForo_Model_Import */
        
$model $this->_importModel;

        
$moderators $sDb->fetchAll('
            SELECT mods.*
            FROM ' 
$prefix 'moderator_cache AS mods
            INNER JOIN ' 
$prefix 'users AS users ON (mods.user_id = users.user_id)
        '
);
        if (!
$moderators)
        {
            return 
true;
        }

        
$modGrouped = array();
        foreach (
$moderators AS $moderator)
        {
            
$modGrouped[$moderator['user_id']][$moderator['forum_id']] = $moderator;
        }

        
$nodeMap $model->getImportContentMap('node');
        
$userIdMap $model->getImportContentMap('user'array_keys($modGrouped));

        
$total 0;

        
XenForo_Db::beginTransaction();

        foreach (
$modGrouped AS $userId => $forums)
        {
            
$newUserId $this->_mapLookUp($userIdMap$userId);
            if (!
$newUserId)
            {
                continue;
            }

            
$inserted false;

            foreach (
$forums AS $forumId => $moderator)
            {
                
$newNodeId $this->_mapLookUp($nodeMap$forumId);
                if (!
$newNodeId)
                {
                    continue;
                }

                
$mod = array(
                    
'content_id' => $newNodeId,
                    
'user_id' => $newUserId,
                    
'moderator_permissions' => $this->_convertForumPermissionsForUser($userId$forumId)
                );
                
$model->importNodeModerator($forumId$userId$mod);

                
$total++;
                
$inserted true;
            }

            if (
$inserted)
            {
                
$mod = array(
                    
'user_id' => $newUserId,
                    
'is_super_moderator' => false,
                    
'moderator_permissions' => array()
                );
                
$model->importGlobalModerator($userId$mod);
            }
        }

        
$this->_session->incrementStepImportTotal($total);

        
XenForo_Db::commit();

        return 
true;
    }

    protected function 
_convertForumPermissionsForUser($userId$forumId)
    {
        
$phpBbPerms $this->_getUserPermissions($userId$forumId);
        
$perms = array('forum' => array());

        if (
$this->_hasPhpBbPerm($phpBbPerms'm_merge') || $this->_hasPhpBbPerm($phpBbPerms'm_move') || $this->_hasPhpBbPerm($phpBbPerms'm_split'))
        {
            
$perms['forum']['manageAnyThread'] = 'content_allow';
            
$perms['forum']['stickUnstickThread'] = 'content_allow';
        }
        if (
$this->_hasPhpBbPerm($phpBbPerms'm_approve'))
        {
            
$perms['forum']['approveUnapprove'] = 'content_allow';
            
$perms['forum']['viewModerated'] = 'content_allow';
        }
        if (
$this->_hasPhpBbPerm($phpBbPerms'm_delete'))
        {
            
$perms['forum']['deleteAnyPost'] = 'content_allow';
            
$perms['forum']['deleteAnyThread'] = 'content_allow';
            
$perms['forum']['undelete'] = 'content_allow';
            
$perms['forum']['viewDeleted'] = 'content_allow';
        }
        
$this->_setXfPermissionBasedOnPermission($perms$phpBbPerms'forum''editAnyPost''m_edit''content_allow');
        
$this->_setXfPermissionBasedOnPermission($perms$phpBbPerms'forum''lockUnlockThread''m_lock''content_allow');

        return 
$perms;
    }

    public function 
stepThreads($start, array $options)
    {
        
$options array_merge(array(
            
'limit' => 100,
            
'postDateStart' => 0,
            
'postLimit' => 800,
            
'max' => false
        
), $options);

        
$sDb $this->_sourceDb;
        
$prefix $this->_prefix;

        
/* @var $model XenForo_Model_Import */
        
$model $this->_importModel;

        if (
$options['max'] === false)
        {
            
$options['max'] = $sDb->fetchOne('
                SELECT MAX(topic_id)
                FROM ' 
$prefix 'topics
            '
);
        }

        
// pull threads from things we actually imported as forums
        
$threads $sDb->fetchAll($sDb->limit(
            
'
                SELECT topics.*,
                    IF(users.username IS NOT NULL, users.username, topics.topic_first_poster_name) AS username
                FROM ' 
$prefix 'topics AS topics FORCE INDEX (PRIMARY)
                LEFT JOIN ' 
$prefix 'users AS users ON (topics.topic_poster = users.user_id)
                INNER JOIN ' 
$prefix 'forums AS forums ON
                    (topics.forum_id = forums.forum_id)
                WHERE topics.topic_id >= ' 
$sDb->quote($start) . '
                    AND topics.topic_status <> 2 # redirect
                ORDER BY topics.topic_id
            '
$options['limit']
        ));
        if (!
$threads)
        {
            return 
true;
        }

        
$next 0;
        
$total 0;
        
$totalPosts 0;

        
$nodeMap $model->getImportContentMap('node');

        
XenForo_Db::beginTransaction();

        foreach (
$threads AS $thread)
        {
            if (
trim($thread['topic_title']) === '')
            {
                continue;
            }

            
$postDateStart $options['postDateStart'];

            
$next $thread['topic_id'] + 1// uses >=, will be moved back down if need to continue
            
$options['postDateStart'] = 0;

            
$maxPosts $options['postLimit'] - $totalPosts;
            
$posts $sDb->fetchAll($sDb->limit(
                
'
                    SELECT posts.*,
                        IF(users.username IS NOT NULL, users.username, posts.post_username) AS username
                    FROM ' 
$prefix 'posts AS posts
                    LEFT JOIN ' 
$prefix 'users AS users ON (posts.poster_id = users.user_id)
                    WHERE posts.topic_id = ' 
$sDb->quote($thread['topic_id']) . '
                        AND posts.post_time > ' 
$sDb->quote($postDateStart) . '
                    ORDER BY posts.post_time
                '
$maxPosts
            
));
            if (!
$posts)
            {
                if (
$postDateStart)
                {
                    
// continuing thread but it has no more posts
                    
$total++;
                }
                continue;
            }

            if (
$postDateStart)
            {
                
// continuing thread we already imported
                
$threadId $model->mapThreadId($thread['topic_id']);

                
$position $this->_db->fetchOne('
                    SELECT MAX(position)
                    FROM xf_post
                    WHERE thread_id = ?
                '
$threadId);
            }
            else
            {
                
$forumId $this->_mapLookUp($nodeMap$thread['forum_id']);
                if (!
$forumId)
                {
                    continue;
                }

                if (
trim($thread['username']) === '')
                {
                    
$thread['username'] = 'Guest';
                }

                
$import = array(
                    
'title' => $this->_convertToUtf8($thread['topic_title'], true),
                    
'node_id' => $forumId,
                    
'user_id' => $model->mapUserId($thread['topic_poster'], 0),
                    
'username' => $this->_convertToUtf8($thread['username'], true),
                    
'discussion_open' => ($thread['topic_status'] == 0),
                    
'post_date' => $thread['topic_time'],
                    
'reply_count' => $thread['topic_replies'],
                    
'view_count' => $thread['topic_views'],
                    
'sticky' => ($thread['topic_type'] == 0),
                    
'last_post_date' => $thread['topic_last_post_time'],
                    
'last_post_username' => $this->_convertToUtf8($thread['topic_last_poster_name'], true),
                );
                if (
$thread['topic_approved'])
                {
                    
$import['discussion_state'] = 'visible';
                }
                else
                {
                    
$import['discussion_state'] = 'moderated';
                }

                
$threadId $model->importThread($thread['topic_id'], $import);
                if (!
$threadId)
                {
                    continue;
                }

                
$position = -1;

                
$subs $sDb->fetchPairs('
                    SELECT user_id, notify_status
                    FROM ' 
$prefix 'topics_watch
                    WHERE topic_id = ' 
$sDb->quote($thread['topic_id'])
                );
                if (
$subs)
                {
                    
$userIdMap $model->getImportContentMap('user'array_keys($subs));
                    foreach (
$subs AS $userId => $emailUpdate)
                    {
                        
$newUserId $this->_mapLookUp($userIdMap$userId);
                        if (!
$newUserId)
                        {
                            continue;
                        }

                        
$model->importThreadWatch($newUserId$threadId, ($emailUpdate 0));
                    }
                }
            }

            if (
$threadId)
            {
                
$quotedPostIds = array();

                
$threadTitleRegex '#^(re:s*)?' preg_quote($thread['topic_title'], '#') . '$#i';

                
$userIdMap $model->getUserIdsMapFromArray($posts'poster_id');

                foreach (
$posts AS $i => $post)
                {
                    if (
$post['post_subject'] !== '' && !preg_match($threadTitleRegex$post['post_subject']))
                    {
                        
$post['post_text'] = '[b]' $post['post_subject'] . "[/b]nn" ltrim($post['post_text']);
                    }

                    if (
trim($post['username']) === '')
                    {
                        
$post['username'] = 'Guest';
                    }

                    
$post['post_text'] = $this->_sanitizeBbCode($post['post_text']);

                    
$import = array(
                        
'thread_id' => $threadId,
                        
'user_id' => $this->_mapLookUp($userIdMap$post['poster_id'], 0),
                        
'username' => $this->_convertToUtf8($post['username'], true),
                        
'post_date' => $post['post_time'],
                        
'message' => $post['post_text'],
                        
'attach_count' => 0,
                        
'ip' => $post['poster_ip']
                    );
                    if (
$post['post_approved'])
                    {
                        
$import['message_state'] = 'visible';
                        
$import['position'] = ++$position;
                    }
                    else
                    {
                        
$import['message_state'] = 'moderated';
                        
$import['position'] = $position;
                    }

                    
$model->importPost($post['post_id'], $import);

                    
$options['postDateStart'] = $post['post_time'];
                    
$totalPosts++;
                }
            }

            if (
count($posts) < $maxPosts)
            {
                
// done this thread
                
$total++;
                
$options['postDateStart'] = 0;
            }
            else
            {
                
// not necessarily done the thread; need to pick it up next page
                
break;
            }
        }

        if (
$options['postDateStart'])
        {
            
// not done this thread, need to continue with it
            
$next--;
        }

        
XenForo_Db::commit();

        
$this->_session->incrementStepImportTotal($total);

        return array(
$next$options$this->_getProgressOutput($next 1$options['max']));
    }

    public function 
stepPolls($start, array $options)
    {
        
$options array_merge(array(
            
'limit' => 100,
            
'max' => false
        
), $options);

        
$sDb $this->_sourceDb;
        
$prefix $this->_prefix;

        
/* @var $model XenForo_Model_Import */
        
$model $this->_importModel;

        if (
$options['max'] === false)
        {
            
$options['max'] = $sDb->fetchOne('
                SELECT MAX(topic_id)
                FROM ' 
$prefix 'poll_options
            '
);
        }

        
$topicIds $sDb->fetchCol($sDb->limit(
            
'
                SELECT topic_id
                FROM ' 
$prefix 'poll_options
                WHERE topic_id > ' 
$sDb->quote($start) . '
                GROUP BY topic_id
                ORDER BY topic_id
            '
$options['limit']
        ));
        if (!
$topicIds)
        {
            return 
true;
        }

        
$threads $sDb->fetchAll('
                SELECT topics.*
                FROM ' 
$prefix 'topics AS topics
                WHERE topics.topic_id IN (' 
$sDb->quote($topicIds) . ')
                ORDER BY topics.topic_id
        '
);
        if (!
$threads)
        {
            return 
true;
        }

        
$next 0;
        
$total 0;

        
$threadIdMap $model->getImportContentMap('thread'$topicIds);

        
XenForo_Db::beginTransaction();

        foreach (
$threads AS $thread)
        {
            
$next $thread['topic_id'];

            
$newThreadId $this->_mapLookUp($threadIdMap$thread['topic_id']);
            if (!
$newThreadId)
            {
                continue;
            }

            if (empty(
$thread['poll_start']))
            {
                continue;
            }

            
$import = array(
                
'question' => $this->_sanitizeBbCode($thread['poll_title'], nulltrue),
                
'multiple' => ($thread['poll_max_options'] > 0),
                
'close_date' => ($thread['poll_length'] ? $thread['poll_start'] + $thread['poll_length'] : 0)
            );
            
$responses $sDb->fetchPairs('
                SELECT poll_option_id, poll_option_text
                FROM ' 
$prefix 'poll_options
                WHERE topic_id = ' 
$sDb->quote($thread['topic_id'])
            );
            foreach (
$responses AS &$value)
            {
                
$value $this->_sanitizeBbCode($valuenulltrue);
            }

            
$newPollId $model->importThreadPoll($thread['topic_id'], $newThreadId$import$responses$responseIds);
            if (
$newPollId)
            {
                
$votes $sDb->fetchAll('
                    SELECT vote_user_id, poll_option_id
                    FROM ' 
$prefix 'poll_votes
                    WHERE topic_id = ' 
$sDb->quote($thread['topic_id'])
                );

                
$userIdMap $model->getUserIdsMapFromArray($votes'vote_user_id');
                foreach (
$votes AS $vote)
                {
                    
$userId $this->_mapLookUp($userIdMap$vote['vote_user_id']);
                    if (!
$userId)
                    {
                        continue;
                    }

                    
$voteOption $vote['poll_option_id'];
                    if (!isset(
$responseIds[$voteOption]))
                    {
                        continue;
                    }

                    
$model->importPollVote($newPollId$userId$responseIds[$voteOption], 0);
                }
            }

            
$total++;
        }

        
XenForo_Db::commit();

        
$this->_session->incrementStepImportTotal($total);

        return array(
$next$options$this->_getProgressOutput($next$options['max']));
    }

    public function 
stepAttachments($start, array $options)
    {
        
$options array_merge(array(
            
'path' => isset($this->_config['attachmentPath']) ? $this->_config['attachmentPath'] : '',
            
'limit' => 50,
            
'max' => false
        
), $options);

        
$sDb $this->_sourceDb;
        
$prefix $this->_prefix;

        
/* @var $model XenForo_Model_Import */
        
$model $this->_importModel;

        if (
$options['max'] === false)
        {
            
$options['max'] = $sDb->fetchOne('
                SELECT MAX(attach_id)
                FROM ' 
$prefix 'attachments
            '
);
        }

        
$attachments $sDb->fetchAll($sDb->limit(
            
'
                SELECT *
                FROM ' 
$prefix 'attachments
                WHERE attach_id > ' 
$sDb->quote($start) . '
                    AND is_orphan = 0
                    AND post_msg_id > 0
                ORDER BY attach_id
            '
$options['limit']
        ));
        if (!
$attachments)
        {
            return 
true;
        }

        
$next 0;
        
$total 0;

        
$userIdMap $model->getUserIdsMapFromArray($attachments'poster_id');
        
$postIdMap $model->getPostIdsMapFromArray($attachments'post_msg_id');

        foreach (
$attachments AS $attachment)
        {
            
$next $attachment['attach_id'];

            
$newPostId $this->_mapLookUp($postIdMap$attachment['post_msg_id']);
            if (!
$newPostId)
            {
                continue;
            }

            
$attachFileOrig "$options[path]/$attachment[physical_filename]";
            if (!
file_exists($attachFileOrig))
            {
                continue;
            }

            
$attachFile tempnam(XenForo_Helper_File::getTempDir(), 'xf');
            
copy($attachFileOrig$attachFile);

            
$success $model->importPostAttachment(
                
$attachment['attach_id'],
                
$this->_convertToUtf8($attachment['real_filename'], true),
                
$attachFile,
                
$this->_mapLookUp($userIdMap$attachment['poster_id'], 0),
                
$newPostId,
                
$attachment['filetime'],
                array(
'view_count' => $attachment['download_count'])
            );
            if (
$success)
            {
                
$total++;
            }

            @
unlink($attachFile);
        }

        
$this->_session->incrementStepImportTotal($total);

        return array(
$next$options$this->_getProgressOutput($next$options['max']));
    }

    protected function 
_sanitizeBbCode($string$bbCodeUid null$strip false)
    {
        if (
$bbCodeUid === null)
        {
            
$bbCodeUidRegex '[a-z0-9]+';
        }
        else
        {
            
$bbCodeUidRegex preg_quote($bbCodeUid'#');
        }

        
// how smilies are stored
        
$string preg_replace(
            
'#<img src="[^"]*" alt="([^"]*)" title="[^"]*"s*/?>#iU',
            
'$1',
            
$string
        
);

        
// seen some email links like this
        
$string preg_replace(
            
'#<a[^>]+href="mailto:([^"]+)">(.*)</a>#siU',
            
'[email=$1]$2[/email]',
            
$string
        
);

        
// seen some links like this
        
$string preg_replace(
            
'#<a[^>]+href="([^"]+)">(.*)</a>#siU',
            
'[url=$1]$2[/url]',
            
$string
        
);

        
// other comment markup
        
$string preg_replace('#<!--.*-->#siU'''$string);

        
$string $this->_convertToUtf8($stringtrue);

        do
        {
            
$previousString $string;

            
// don't handle converting [attachment] tags - just strip them
            
$string preg_replace(
                
'#[attachment="?.*"?:(' $bbCodeUidRegex ')].*[/attachment:\1]#siU',
                
'',
                
$string
            
);

            
// size tags need mapping
            
$string preg_replace_callback(
                
'#[(size)="?([^]]*)"?:(' $bbCodeUidRegex ')](.*)[/size:\3]#siU',
                array(
$this'_handleBbCodeSizeCallback'),
                
$string
            
);

            
// align tags need mapping
            
$string preg_replace(
                
'#[align="?(left|center|right)"?:(' $bbCodeUidRegex ')](.*)[/align:\2]#siU',
                
'[$1]$3[/$1]',
                
$string
            
);
        }
        while (
$string != $previousString);

        
$string preg_replace(
            
'#[([a-z0-9_*]+(="[^"]*"|=[^]]*)?):(' $bbCodeUidRegex ')]#siU',
            (
$strip '' '[$1]'),
            
$string
        
);
        
$string preg_replace(
            
'#[/([a-z0-9_*]+)(:[a-z])?:(' $bbCodeUidRegex ')]#siU',
            (
$strip '' '[/$1]'),
            
$string
        
);

        
$string str_replace('[/*]'''$string);

        return 
$string;
    }

    protected function 
_handleBbCodeSizeCallback(array $match)
    {
        
$tag $match[1];
        
$size intval($match[2]);
        
$text $match[4];

        if (
$size >= 200)
        {
            
$size 7;
        }
        else if (
$size >= 170)
        {
            
$size 6;
        }
        else if (
$size >= 140)
        {
            
$size 5;
        }
        else if (
$size >= 110)
        {
            
$size 4;
        }
        else if (
$size >= 90)
        {
            
$size 3;
        }
        else if (
$size >= 60)
        {
            
$size 2;
        }
        else
        {
            
$size 1;
        }

        return 
'[' $tag '=' $size ']' $text '[/' $tag ']';
    }
}
Онлайн: 2
Реклама