Файл: 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']) ? 1 : $groups[$group['id']]['leader'],
'user_pending' => (!$group['pending']) ? 0 : $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 ' . $table, E_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 ' . $table, E_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;
}
}