Вход Регистрация
Файл: apwa/stk/tools/usergroup/merge_users.php
Строк: 470
<?php
/**
*
* @package Support Toolkit - Merge Users
* @version $Id$
* @author Chris Smith <toonarmy@phpbb.com> (http://www.cs278.org/)
* @copyright (c) 2009 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU License
*
*/

/**
 * @ignore
 */
if (!defined('IN_PHPBB'))
{
    exit;
}

class 
merge_users
{
    
/**
    * Display Options
    *
    * Output the options available
    */
    
function display_options()
    {
        global 
$user;

        return array(
            
'title'        => 'MERGE_USERS',
            
'explain'    => true,
            
'vars'        => array(
                
'legend1'        => 'MERGE_USERS',
                
'source_name'    => array('lang' => 'MERGE_USERS_USER_SOURCE_NAME''type' => 'text:40:255''explain' => true'select_user' => true),
                
'source_id'        => array('lang' => 'MERGE_USERS_USER_SOURCE_ID''type' => 'text:10:50''explain' => false'select_user' => false),
                
'target_name'    => array('lang' => 'MERGE_USERS_USER_TARGET_NAME''type' => 'text:40:255''explain' => false'select_user' => true),
                
'target_id'        => array('lang' => 'MERGE_USERS_USER_TARGET_ID''type' => 'text:10:50''explain' => false'select_user' => false),
                
'delete'        => array('lang' => 'MERGE_USERS_REMOVE_SOURCE''type' => 'checkbox''explain' => true'default' => true),
            ),
        );
    }

    
/**
    * Run Tool
    *
    * Does the actual stuff we want the tool to do after submission
    */
    
function run_tool(&$error)
    {
        global 
$config$user$db$cache;

        
$user->add_lang('ucp');

        if (!
check_form_key('merge_users'))
        {
            
$error[] = 'FORM_INVALID';
            return;
        }

        
$source_name utf8_normalize_nfc(request_var('source_name'''true));
        
$source_id utf8_normalize_nfc(request_var('source_id'0));
        
$target_name utf8_normalize_nfc(request_var('target_name'''true));
        
$target_id utf8_normalize_nfc(request_var('target_id'0));
        
$delete request_var('delete'false);

        
// Check that one source field and one target field is filled in.
        
if ((!$source_name && empty($source_id)) || (!$target_name && empty($target_id)))
        {
            if (!
$source_name && !$source_id)
            {
                
$error[] = 'NO_SOURCE_USER';
            }
            if (!
$target_name && !$target_id)
            {
                
$error[] = 'NO_TARGET_USER';
            }
            return;
        }

        
// Check if both source fields or both target fields are filled in.
        
if (($source_name && $source_id) || ($target_name && $target_id))
        {
            if (
$source_name && $source_id)
            {
                
$error[] = 'BOTH_SOURCE_USER';
            }
            if (
$target_name && $target_id)
            {
                
$error[] = 'BOTH_TARGET_USER';
            }
            return;
        }

        
$sql 'SELECT user_id, user_type 
            FROM ' 
USERS_TABLE '
            WHERE ' 
. (($source_name) ? 'username_clean = '' . $db->sql_escape(utf8_clean_string($source_name)) . ''' 'user_id = ' . (int) $source_id);
        
$result $db->sql_query($sql);
        
$source $db->sql_fetchrow($result);
        
$db->sql_freeresult($result);

        
$sql 'SELECT user_id, user_type 
            FROM ' 
USERS_TABLE '
            WHERE ' 
. (($target_name) ? 'username_clean = '' . $db->sql_escape(utf8_clean_string($target_name)) . ''' 'user_id = ' . (int) $target_id);

        
$result $db->sql_query($sql);
        
$target $db->sql_fetchrow($result);
        
$db->sql_freeresult($result);

        if (!
$source || !$target)
        {
            if (!
$source)
            {
                
$error[] = 'NO_SOURCE_USER';
            }
            if (!
$target)
            {
                
$error[] = 'NO_TARGET_USER';
            }
            return;
        }

        if (
$source['user_id'] == $target['user_id'])
        {
            
$error[] = 'MERGE_USERS_SAME_USERS';
            return;
        }

        if (
$source['user_type'] != $target['user_type'])
        {
            if (
$source['user_type'] == USER_FOUNDER || $target['user_type'] == USER_FOUNDER)
            {
                
// Cannot merge a founder with a non founder or vice versa
                
$error[] = 'MERGE_USERS_BOTH_FOUNDERS';
                return;
            }
            else if (
$source['user_type'] == USER_IGNORE || $target['user_type'] == USER_IGNORE)
            {
                
// Cannot merge a bot with a non bot or vice versa
                
$error[] = 'MERGE_USERS_BOTH_IGNORE';
                return;
            }
        }

        
$source = (int) $source['user_id'];
        
$target = (int) $target['user_id'];

        
// Needed for the merge
        
include PHPBB_ROOT_PATH 'includes/functions_user.' PHP_EXT;

        
$result $this->merge($source$target);

        if (
is_string($result))
        {
            
$error[] = $result;
            return;
        }

        
$db->sql_transaction('begin');

        foreach (
$result as $sql)
        {
            
$db->sql_query($sql);
        }

        
$db->sql_transaction('commit');

        
// Delete source user
        
if ($delete)
        {
            
user_delete('remove'$source$post_username false);
        }

        
$sql 'SELECT DISTINCT group_id
            FROM ' 
USER_GROUP_TABLE "
            WHERE user_id IN (
$source$target)";
        
$result $db->sql_query($sql);

        while (
$row $db->sql_fetchrow($result))
        {
            
group_update_listings((int) $row['group_id']);
        }
        
$db->sql_freeresult($result);

        
// Update data
        
update_last_username();
        
$cache->destroy('sql'MODERATOR_CACHE_TABLE);

        
trigger_error('MERGE_USERS_MERGED');
    }

    function 
merge($source$target)
    {
        global 
$db;

        
$source $this->get_user_data($source);
        
$target $this->get_user_data($target);

        
$groups $this->get_group_memberships($target['user_id']);

        
$types = array(
            
'id'        => 'user_id',
            
'name'        => 'username',
            
'colour'    => 'user_colour',
        );

        
$sql = array(
        );

        foreach (
$this->get_group_memberships($source['user_id']) as $group)
        {
            if (isset(
$groups[$group['id']]))
            {
                if (
$groups[$group['id']]['leader'] != $group['leader'] || $groups[$group['id']]['pending'] != $group['pending'])
                {
                    
$sql[] = 'UPDATE ' USER_GROUP_TABLE '
                        SET ' 
$db->sql_build_array('UPDATE', array(
                            
'group_leader'    => ($group['leader']) ? $groups[$group['id']]['leader'],
                            
'user_pending'    => (!$group['pending']) ? $groups[$group['id']]['pending'],
                        )) . 
"
                        WHERE user_id = 
{$target['user_id']}
                            AND group_id = 
{$group['id']}";
                }
            }
            else
            {
                
$sql[] = 'INSERT INTO ' USER_GROUP_TABLE ' ' $db->sql_build_array('INSERT', array(
                    
'group_id'        => $group['id'],
                    
'user_id'        => $target['user_id'],
                    
'group_leader'    => $group['leader'],
                    
'user_pending'    => $group['pending'],
                ));
            }
        }

        
/**
         * Ignored tables
         * forums_access
         * sessions
         * sessions_keys
         */
        
foreach (array(
            
'acl_users'        => null,
            
'attachments'    => 'poster_id',

            
'banlist'    => 'ban_userid',
            
'bookmarks'    => null,
            
'bots'        => 'user_id',

            
'drafts'    => 'user_id',

            
'forums'        => array(
                array(
                    
'forum_last_poster_id'        => 'id',
                    
'forum_last_poster_name'    => 'name',
                    
'forum_last_poster_colour'    => 'colour',
                ),
                array(
                    
'forum_last_poster_id',
                    array(
'forum_last_poster_id''forum_last_poster_name''forum_last_poster_colour'),
                ),
            ),

            
'forums_track'    => null,
            
'forums_watch'    => null,

            
'log'    => array(
                array(
                    
'user_id'        => 'id',
                    
'reportee_id'    => 'id',
                ),
                array(
                    
'user_id',
                    
'user_id',
                ),
                array(
                    
'reportee_id',
                    
'reportee_id',
                ),
            ),

            
'moderator_cache' => array(
                array(
                    
'user_id'        => 'id',
                    
'username'        => 'name',
                ),
                array(
                    
'user_id',
                    array(
'user_id''username'),
                ),
            ),

            
'poll_votes'            => 'vote_user_id',
            
'posts'                    => array(
                array(
                    
'poster_id'        => 'id',
                    
'post_username'    => 'name',
                ),
                array(
                    
'poster_id',
                    array(
'poster_id''post_username'),
                ),
            ),
            
'privmsgs'                => array(
                array(
                    
'author_id'        => 'id',
                ),
                array(
                    
'author_id',
                    
'author_id',
                ),
                
null,
            ),
            
// Only custom folders making this easy as 3.14159
            
'privmsgs_folder'        => array(
                array(
                    
'user_id'        => 'id',
                ),
                array(
                    
'user_id',
                    
'user_id',
                ),
            ),
            
'privmsgs_rules'        => array(
                array(
                    
'user_id'        => 'id',
                    
'rule_user_id'    => 'id',
                    
'rule_string'    => 'name'// Not all the time
                
),
                
// Rules referencing our source user
                
array(
                    
'rule_user_id',
                    array(
'rule_user_id''rule_string'),
                ),
                
// Rules created by our source user
                
array(
                    
'user_id',
                    
'user_id',
                ),
            ),
            
'privmsgs_to'            => array(
                array(
                    
'user_id'    => 'id'// Destination user
                    
'author_id'    => 'id'// Author
                
),
                array(
                    
'user_id',
                    
'user_id',
                ),
                array(
                    
'author_id',
                    
'author_id',
                ),
            ),
            
'profile_fields_data'    => null,

            
'reports'    => 'user_id',

            
'topics'        => array(
                array(
                    
'topic_poster'                => 'id',
                    
'topic_first_poster_name'    => 'name',
                    
'topic_first_poster_colour'    => 'colour',
                    
'topic_last_poster_id'        => 'id',
                    
'topic_last_poster_name'    => 'name',
                    
'topic_last_poster_colour'    => 'colour',
                ),
                array(
                    
'topic_poster',
                    
'topic_poster',
                ),
                array(
                    array(
'topic_first_poster_name''topic_first_poster_colour'),
                    array(
'topic_first_poster_name''topic_first_poster_colour'),
                ),
                array(
                    
'topic_last_poster_id',
                    array(
'topic_last_poster_id''topic_last_poster_name''topic_last_poster_colour'),
                ),
            ),
            
'topics_posted'    => null,
            
'topics_track'    => null,
            
'topics_watch'    => null,

            
'warnings'        => 'user_id',

            
'zebra'            => null,
        ) as 
$key => $data)
        {
            if (
is_string($data))
            {
                
// Simple
                
$table $this->table_name($key);

                
$sql[] = "UPDATE $table
                    SET 
$data = {$target['user_id']}
                    WHERE 
$data = {$source['user_id']}";
            }
            else if (
is_null($data))
            {
                
$method 'merge_' $key;

                
$sql array_merge($sql, (array) $this->$method($source$target));
            }
            else if (
is_array($data))
            {
                
$table $this->table_name($key);

                
// Column types
                
$columns array_shift($data);

                
// Magic foo
                
foreach ($data as $update)
                {
                    if (
is_null($update))
                    {
                        
$method 'merge_' $key;

                        
$sql array_merge($sql, (array) $this->$method($source$target));

                        continue;
                    }
                    
$find array_shift($update);
                    
$replace array_shift($update);

                    
$update $where = array();

                    if (!
is_array($find))
                    {
                        
$find = array($find);
                    }

                    if (!
is_array($replace))
                    {
                        
$replace = array($replace);
                    }

                    foreach (
$find as $column)
                    {
                        if (!isset(
$columns[$column]))
                        {
                            
trigger_error('Missing column [' htmlspecialchars($column) . '] in ' $tableE_USER_ERROR);
                        }
                        
$where[] = $column ' = ' $db->_sql_validate_value($source[$types[$columns[$column]]]);
                    }

                    foreach (
$replace as $column)
                    {
                        if (!isset(
$columns[$column]))
                        {
                            
trigger_error('Missing column [' htmlspecialchars($column) . '] in ' $tableE_USER_ERROR);
                        }
                        
$update[$column] = $target[$types[$columns[$column]]];
                    }

                    
$sql[] = "UPDATE $table
                        SET " 
$db->sql_build_array('UPDATE'$update) . '
                        WHERE ' 
implode(' AND '$where);
                }
            }
        }

        
$update['target'] = $update['source'] = $update = array();

        if (
$source['user_type'] !== $target['user_type'])
        {
            if (
$source['user_type'] == USER_FOUNDER || $target['user_type'] == USER_FOUNDER)
            {
                
// Cannot merge a founder with a non founder or vice versa
                
return 'MERGE_USERS_BOTH_FOUNDERS';
            }
            else if (
$source['user_type'] == USER_IGNORE || $target['user_type'] == USER_IGNORE)
            {
                
// Cannot merge a bot with a non bot or vice versa
                
return 'MERGE_USERS_BOTH_IGNORE';
            }

            switch (
$source['user_type'])
            {
                case 
USER_INACTIVE:
                    
$update['target']['user_type']                = USER_INACTIVE;
                    
$update['target']['user_inactive_reason']    = $source['user_inactive_reason'];
                    
$update['target']['user_inactive_time']        = (int) $source['user_inactive_time'];
                    
$update['target']['user_reminded']            = (int) $source['user_reminded'];
                    
$update['target']['user_reminded_time']        = (int) $source['user_reminded_time'];
                    
$update['target']['user_actkey']            = $source['user_actkey'];
                    
$update['target']['user_newpasswd']            = $source['user_newpasswd'];
                break;

                case 
USER_NORMAL:
                break;
            }
        }

        
// Reset permissions
        
$update['source']['user_permissions'] = $update['target']['user_permissions'] = '';
        
$update['source']['user_perm_from'] = $update['target']['user_perm_from'] = 0;

        if (
$source['user_regdate'] < $target['user_regdate'])
        {
            
// Source user registered first, update registration data
            
$update['target']['user_regdate']    = (int) $source['user_regdate'];
            
$update['target']['user_ip']        = $source['user_ip'];
        }

        foreach (array(
'lastvisit''lastmark''lastpost_time''last_search''last_warning''last_privmsg''emailtime''full_folder') as $var)
        {
            if (
$source['user_' $var] > $target['user_' $var])
            {
                
// Source users value is newer update
                
$update['target']['user_' $var] = (int) $source['user_' $var];
            }
        }

        if (isset(
$update['target']['user_lastvisit']))
        {
            
// Updating lastvisit, update other last stuff
            
$update['target']['user_lastpage'] = $source['user_lastpage'];
        }

        foreach (array(
'posts''warnings''login_attempts''new_privmsg''unread_privmsg') as $var)
        {
            if (
$source['user_' $var])
            {
                
$update['target']['user_' $var] = $source['user_' $var] + $target['user_' $var];
                
$update['source']['user_' $var] = 0;
            }
        }

        if (
$source['user_message_rules'])
        {
            
// Update this only if the source has rules
            
if (!$target['user_message_rules'])
            {
                
$update['target']['user_message_rules'] = 1;
            }
            
// No longer has rules ;)
            
$update['source']['user_message_rules'] = 0;
        }

        if (
$source['user_notify_type'] != $target['user_notify_type'] && $target['user_notify_type'] != NOTIFY_BOTH)
        {
            
// Not the same, and target is not both, therefore one is jabber and one is email or otherway around
            // Merge by setting to both
            
$update['target']['user_notify_type'] = NOTIFY_BOTH;
        }

        foreach (array(
'birthday''avatar''sig''from''icq''aim''yim''msnm''jabber''website''occ''interests') as $var)
        {
            if (!
$target['user_' $var] && $source['user_' $var])
            {
                
$update['target']['user_' $var] = $source['user_' $var];

                switch (
$var)
                {
                    case 
'avatar':
                        
$update['target']['user_avatar_type']    = $source['user_avatar_type'];
                        
$update['target']['user_avatar_width']    = $source['user_avatar_width'];
                        
$update['target']['user_avatar_height']    = $source['user_avatar_height'];
                    break;

                    case 
'sig':
                        
$update['target']['user_sig_bbcode_uid']        = $source['user_sig_bbcode_uid'];
                        
$update['target']['user_sig_bbcode_bitfield']    = $source['user_sig_bbcode_bitfield'];
                    break;
                }
            }
        }

        
// Options
        
if (($source['user_options'] | $target['user_options']) !== $source['user_options'])
        {
            
// Any bits set in source OR target are set
            
$source['user_options'] = $source['user_options'] | $target['user_options'];
        }

        
// Update user_new if both 1 and passes threshold

        // Default group
        // Source user is not removed from groups so no need to update this
        
if (!$target['user_rank'] && !$target['user_colour'] && ($source['user_rank'] || $source['user_colour']))
        {
            
// No rank or colour on target and source has rank or colour update default group
            
$update['target']['group_id'] = $source['group_id'];
            
$update['target']['user_colour'] = $source['user_colour'];
            
$update['target']['user_rank'] = $source['user_rank'];
        }

        
$sql[] = 'UPDATE ' USERS_TABLE '
            SET ' 
$db->sql_build_array('UPDATE'$update['source']) . "
            WHERE user_id = 
{$source['user_id']}";

        
$sql[] = 'UPDATE ' USERS_TABLE '
            SET ' 
$db->sql_build_array('UPDATE'$update['target']) . "
            WHERE user_id = 
{$target['user_id']}";

        return 
$sql;
    }

    function 
merge_acl_users($source$target)
    {
        global 
$db;

        
$acls['source'] = $acls['target'] = $acls = array();

        
$sql_ary = array(
            
'SELECT'    => 'au.*, ard.auth_setting AS role_setting',
            
'FROM'        => array(
                
ACL_USERS_TABLE => 'au',
            ),
            
'LEFT_JOIN'    => array(
                array(
                    
'FROM'    => array(
                        
ACL_ROLES_DATA_TABLE => 'ard',
                    ),
                    
'ON'    => 'au.auth_role_id = ard.role_id
                                AND au.auth_option_id = ard.auth_option_id'
,
                ),
            ),
            
'WHERE'        => $db->sql_in_set('user_id', array($source['user_id'], $target['user_id'])),
        );
        
$sql $db->sql_build_query('SELECT'$sql_ary);

        
$result $db->sql_query($sql);

        while (
$row $db->sql_fetchrow($result))
        {
            
$key = ($row['user_id'] == $source['user_id'] ? 'source' 'target');
            
$setting = (int) ($row['auth_role_id'] ? $row['role_setting'] : $row['auth_setting']);

            if (!isset(
$acls[$key][(int) $row['auth_option_id']]))
            {
                
$acls['source'][(int) $row['auth_option_id']] = $acls['target'][(int) $row['auth_option_id']] = array();
            }

            
$acls[$key][(int) $row['auth_option_id']][(int) $row['forum_id']] = array(
                
'role'        => (int) $row['auth_role_id'],
                
'setting'    => $setting,
            );
        }
        
$db->sql_freeresult($result);

        
$sql = array();

        foreach (
$acls['source'] as $id => $forums)
        {
            foreach (
$forums as $fid => $data)
            {
                
$insert $update = array();

                if (isset(
$acls['target'][$id][$fid]))
                {
                    if (
$data['setting'] === $acls['target'][$id][$fid]['setting'])
                    {
                        
// Same setting
                        
if ($data['role'] === $acls['target'][$id][$fid]['role'])
                        {
                            
// Same role
                            
continue;
                        }
                        else if (
$data['role'] && !$acls['target'][$id][$fid]['role'])
                        {
                            
// Source has a role, target doesn't, favour roles
                            
$update = array(
                                
'auth_role_id'    => $data['role'],
                                
'auth_setting'    => 0,
                            );
                        }
                        else
                        {
                            
// Both have different roles with the same settings, keep the current role
                            
continue;
                        }
                    }
                    else if (
$acls['target'][$id][$fid]['setting'] === ACL_NEVER)
                    {
                        
// Target has been set to never, we do not wish to replace this
                        
continue;
                    }
                    else if (
$data['setting'] == ACL_NO)
                    {
                        
// Source has no ACL defined
                        // The first condition will catch NO && NO but differing roles
                        
continue;
                    }
                    else
                    {
                        
// Source is not NO and target is not NEVER

                        /**
                         * Source    | Target
                         *     Y        |    Y
                         *     N        |
                         *             |    ∅
                         *
                         * Y => ∅
                         * N => Y
                         * N => ∅
                         */

                        
if (!$data['role'] && !$acls['target'][$id][$fid]['role'])
                        {
                            
// Neither have a role
                            
if ($acls['target'][$id][$fid]['setting'] === ACL_NO)
                            {
                                
// Overwrite an ACL_NO
                                
$update = array(
                                    
'auth_setting'    => $data['setting'],
                                );
                            }
                            else
                            {
                                continue;
                            }
                        }
                        else if (
$data['role'] && !$acls['target'][$id][$fid]['role'])
                        {
                            
// Source has a role overwrite
                            
$update = array(
                                
'auth_role_id'    => $data['role'],
                                
'auth_setting'    => 0,
                            );
                        }
                        else
                        {
                            
// Source has no role, target has role
                            
continue;
                        }
                    }
                }
                else
                {
                    
// Target has nothing set here, insert
                    
$insert = array(
                        
'user_id'            => $target['user_id'],
                        
'forum_id'            => $fid,
                        
'auth_option_id'    => $id,
                    );

                    if (
$data['role'])
                    {
                        
$insert['auth_role_id'] = $data['role'];
                    }
                    else
                    {
                        
$insert['auth_setting'] = $data['setting'];
                    }
                }

                if (
$insert)
                {
                    
$sql[] = 'INSERT INTO ' ACL_USERS_TABLE ' ' $db->sql_build_array('INSERT'$insert);
                }
                else if (
$update)
                {
                    
$sql[] = 'UPDATE ' ACL_USERS_TABLE '
                        SET ' 
$db->sql_build_array('UPDATE'$update) . "
                        WHERE user_id = 
{$target['user_id']}
                            AND forum_id = 
$fid
                            AND auth_option_id = 
$id";
                }
            }
        }
        return 
$sql;
    }

    function 
merge_bookmarks($source$target)
    {
        global 
$db;

        
$bookmarks = array();

        
$sql 'SELECT topic_id
            FROM ' 
BOOKMARKS_TABLE "
            WHERE user_id = 
{$target['user_id']}";

        
$result $db->sql_query($sql);

        while (
$row $db->sql_fetchrow($result))
        {
            
$bookmarks[] = (int) $row['topic_id'];
        }
        
$db->sql_freeresult($result);

        
$sql = array();

        if (!empty(
$bookmarks))
        {
            
// Delete duplicate bookmarks
            
$sql[] = 'DELETE
                FROM ' 
BOOKMARKS_TABLE "
                WHERE user_id = 
{$source['user_id']}
                    AND " 
$db->sql_in_set('topic_id'$bookmarks);
        }

        
// Update remaining bookmarks
        
$sql[] = 'UPDATE ' BOOKMARKS_TABLE "
            SET user_id    = 
{$target['user_id']}
            WHERE user_id = 
{$source['user_id']}";

        return 
$sql;
    }

    function 
merge_forums_track($source$target)
    {
        return 
$this->merge_track_tables('forum'$source$target);
    }

    function 
merge_forums_watch($source$target)
    {
        return 
$this->merge_watch_tables('forum'$source$target);
    }

    function 
merge_privmsgs($source$target)
    {
        global 
$db;

        
$sql 'SELECT msg_id, to_address, bcc_address
            FROM ' 
PRIVMSGS_TABLE "
            WHERE to_address LIKE '%u_
{$source['user_id']}%'
                OR bcc_address LIKE '%u_
{$source['user_id']}%'";
        
$result $db->sql_query($sql);

        
$sql = array();

        while (
$row $db->sql_fetchrow($result))
         {
            
$to_id explode(':',$row['to_address']);
            foreach (
$to_id as $key => $v1)
            {
                
$trimmed = (int) ltrim($v1'u_');
                if (
$trimmed === $source['user_id'])
                {
                    
$to_id[$key] = 'u_' $target['user_id'];
                }
            }
            
$to_address implode(':'$to_id);

            
$bcc_id explode(':',$row['bcc_address']);
            foreach (
$bcc_id as $key => $v1)
            {
                
$trimmed = (int) ltrim($v1'u_');
                if (
$trimmed === $source['user_id'])
                {
                    
$bcc_id[$key] = 'u_' $target['user_id'];
                }
            }
            
$bcc_address implode(':'$bcc_id);


             
$sql[] = 'UPDATE ' PRIVMSGS_TABLE '
                 SET ' 
$db->sql_build_array('UPDATE', array(
                    
'to_address'    => $to_address,
                    
'bcc_address'    => $bcc_address,
             )) . 
'
             WHERE msg_id = ' 
. (int) $row['msg_id'];
         }

        return 
$sql;
    }

    function 
merge_profile_fields_data($source$target)
    {
        global 
$db;

        
$fields = array();

        
$sql 'SELECT *
            FROM ' 
PROFILE_FIELDS_DATA_TABLE "
            WHERE user_id = 
{$source['user_id']}";
        
$result $db->sql_query($sql);
        
$fields['source'] = $db->sql_fetchrow($result);
        
$db->sql_freeresult($result);

        
$sql 'SELECT *
            FROM ' 
PROFILE_FIELDS_DATA_TABLE "
            WHERE user_id = 
{$target['user_id']}";
        
$result $db->sql_query($sql);
        
$fields['target'] = $db->sql_fetchrow($result);
        
$db->sql_freeresult($result);

        unset(
$fields['source']['user_id'], $fields['target']['user_id']);

        if (empty(
$fields['source']))
        {
            return array();
        }

        foreach (
$fields['source'] as $name => $value)
        {
            if (empty(
$fields['target']) || $fields['target'][$name] === null)
            {
                
$update[$name] = $value;
            }
        }

        if (empty(
$update))
        {
            return array();
        }

        return array(
            
'UPDATE ' PROFILE_FIELDS_DATA_TABLE '
                SET ' 
$db->sql_build_array('UPDATE'$update) . "
                WHERE user_id = 
{$target['user_id']}",
            
'DELETE
                FROM ' 
PROFILE_FIELDS_DATA_TABLE "
                WHERE user_id = 
{$source['user_id']}",
        );
    }

    function 
merge_topics_posted($source$target)
    {
        global 
$db;

        
$posted = array();

        
$sql 'SELECT topic_id, topic_posted
            FROM ' 
TOPICS_POSTED_TABLE "
            WHERE user_id = 
{$target['user_id']}";

        
$result $db->sql_query($sql);

        while (
$row $db->sql_fetchrow($result))
        {
            
// Should never be zero but you never know
            
if ($row['topic_posted'])
            {
                
$posted[] = (int) $row['topic_id'];
            }
        }
        
$db->sql_freeresult($result);

        
$sql = array();

        if (!empty(
$posted))
        {
            
// Delete duplicates
            
$sql[] = 'DELETE
                FROM ' 
TOPICS_POSTED_TABLE "
                WHERE user_id = 
{$source['user_id']}
                    AND " 
$db->sql_in_set('topic_id'$posted);
        }

        
// Update remaining
        
$sql[] = 'UPDATE ' TOPICS_POSTED_TABLE "
            SET user_id    = 
{$target['user_id']}
            WHERE user_id = 
{$source['user_id']}";

        return 
$sql;
    }

    function 
merge_topics_track($source$target)
    {
        return 
$this->merge_track_tables('topic'$source$target);
    }

    function 
merge_topics_watch($source$target)
    {
        return 
$this->merge_watch_tables('topic'$source$target);
    }

    function 
merge_zebra($source$target)
    {
        global 
$db;

        
$friends $foes = array();

        
$sql 'SELECT zebra_id, friend, foe
            FROM ' 
ZEBRA_TABLE "
            WHERE user_id = 
{$target['user_id']}
                AND zebra_id <> 
{$target['user_id']}";

        
$result $db->sql_query($sql);

        while (
$row $db->sql_fetchrow($result))
        {
            if (
$row['friend'])
            {
                
$friends[] = (int) $row['zebra_id'];
            }
            else if (
$row['foe'])
            {
                
$foes[] = (int) $row['zebra_id'];
            }
        }
        
$db->sql_freeresult($result);

        
$sql = array();

        if (!empty(
$friends) || !empty($foes))
        {
            
// Delete duplicates
            
$sql[] = 'DELETE
                FROM ' 
ZEBRA_TABLE "
                WHERE user_id = 
{$source['user_id']}
                    AND " 
$db->sql_in_set('zebra_id'array_merge($friends$foes));
        }

        
// Update remaining
        
$sql[] = 'UPDATE ' ZEBRA_TABLE "
            SET user_id    = 
{$target['user_id']}
            WHERE user_id = 
{$source['user_id']}";

        return 
$sql;
    }

    function 
merge_watch_tables($mode$source$target)
    {
        global 
$db;

        
$table $this->table_name($mode 's_watch');
        
$watches = array();

        
$sql "SELECT {$mode}_id, notify_status
            FROM 
$table
            WHERE user_id = 
{$target['user_id']}";

        
$result $db->sql_query($sql);

        while (
$row $db->sql_fetchrow($result))
        {
            
$watches[(int) $row[$mode '_id']] = (bool) $row['notify_status'];
        }
        
$db->sql_freeresult($result);

        
$sql "SELECT {$mode}_id, notify_status
            FROM 
$table
            WHERE user_id = 
{$source['user_id']}";

        
$result $db->sql_query($sql);

        
$sql = array();

        while (
$row $db->sql_fetchrow($result))
        {
            
$id = (int) $row[$mode '_id'];

            
// Don't update anything if both users are watching
            
if (!isset($watches[$id]))
            {
                
$sql[] = "INSERT INTO $table " $db->sql_build_array('INSERT', array(
                    
'user_id'        => $target['user_id'],
                    
"{$mode}_id"    => $id,
                    
'notify_status'    => 0,    // So emails are sent
                
));
            }
        }
        
$db->sql_freeresult($result);

        
// Clean up
        
$sql[] = "DELETE
            FROM 
$table
            WHERE user_id = 
{$source['user_id']}";

        return 
$sql;
    }

    function 
merge_track_tables($mode$source$target)
    {
        global 
$db;

        
$table $this->table_name($mode 's_track');
        
$marks = array();

        
$sql "SELECT {$mode}_id, mark_time
            FROM 
$table
            WHERE user_id = 
{$target['user_id']}";

        
$result $db->sql_query($sql);

        while (
$row $db->sql_fetchrow($result))
        {
            
$marks[(int) $row[$mode '_id']] = (int) $row['mark_time'];
        }
        
$db->sql_freeresult($result);

        
$sql "SELECT {$mode}_id, mark_time
            FROM 
$table
            WHERE user_id = 
{$source['user_id']}";

        
$result $db->sql_query($sql);

        
$sql = array();

        while (
$row $db->sql_fetchrow($result))
        {
            
$id = (int) $row[$mode '_id'];
            
$time = (int) $row['mark_time'];

            if (isset(
$marks[$id]) && $time $marks[$id]['time'])
            {
                
$sql[] = "UPDATE $table
                    SET mark_time = 
$time
                    WHERE user_id = 
{$target['user_id']}
                        AND 
{$mode}_id = $id";
            }
            else if (!isset(
$marks[$id]))
            {
                
// Shouldn't mess up topics tracking without a forum_id
                
$sql[] = "INSERT INTO $table " $db->sql_build_array('INSERT', array(
                    
'user_id'    => $target['user_id'],
                    
"{$mode}_id"=> $id,
                    
'mark_time'    => $time,
                ));
            }
        }
        
$db->sql_freeresult($result);

        
$sql[] = "DELETE
            FROM 
$table
            WHERE user_id = 
{$source['user_id']}";

        return 
$sql;
    }

    function 
table_name($table)
    {
        
$table strtoupper($table) . '_TABLE';

        if (!
defined($table))
        {
            
trigger_error('Table is missing ' $table);
        }
        return 
constant($table);
    }

    function 
get_user_data($user)
    {
        global 
$db;

        
$sql 'SELECT *
            FROM ' 
USERS_TABLE '
            WHERE user_id = ' 
. (int) $user;

        
$result $db->sql_query($sql);
        
$data $db->sql_fetchrow($result);
        
$db->sql_freeresult($result);

        
// Cast some values
        
return array_merge($data, array(
            
'user_id'    => (int) $data['user_id'],
        ));
    }

    function 
get_group_memberships($user)
    {
        
$groups        = array();
        
$group_set    group_memberships(false, (int) $user);

        foreach (
$group_set as $group)
        {
            
$groups[(int) $group['group_id']] = array(
                
'id'        => (int) $group['group_id'],
                
'leader'    => (bool) $group['group_leader'],
                
'pending'    => (bool) $group['user_pending'],
            );
        }
        return 
$groups;
    }
}
Онлайн: 4
Реклама