/** * Merge two users * * @param integer $sourceuserid * @param integer $destuserid */ public function merge($sourceuserid, $destuserid) { $this->checkHasAdminPermission('canadminusers'); $assertor = vB::getDbAssertor(); if (!($sourceinfo = $assertor->getRow('user_fetchwithtextfield', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_STORED, 'userid' => $sourceuserid)))) { throw new vB_Exception_Api('invalid_source_username_specified'); } if (!($destinfo = $assertor->getRow('user_fetchwithtextfield', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_STORED, 'userid' => $destuserid)))) { throw new vB_Exception_Api('invalid_destination_username_specified'); } /* // Update Subscribed Forums $assertor->assertQuery('userInsertSubscribeforum', array( vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_METHOD, 'sourceuserid' => $sourceinfo['userid'], 'destuserid' => $destinfo['userid'], )); $assertor->assertQuery('user_updatesubscribethread', array( 'userid' => $destinfo['userid'], )); $assertor->assertQuery('userInsertSubscribethread', array( vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_METHOD, 'sourceuserid' => $sourceinfo['userid'], 'destuserid' => $destinfo['userid'], )); require_once(DIR . '/includes/functions_databuild.php'); update_subscriptions(array('userids' => array($destinfo['userid']))); */ // Update Subscribed Events $assertor->assertQuery('userInsertSubscribeevent', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_METHOD, 'sourceuserid' => $sourceinfo['userid'], 'destuserid' => $destinfo['userid'])); /* REPLACE INTO */ // Merge relevant data in the user table // It is ok to have duplicate ids in the buddy/ignore lists $userdm = new vB_Datamanager_User(vB_DataManager_Constants::ERRTYPE_SILENT); $userdm->set_existing($destinfo); $options = vB::getDatastore()->getValue('options'); $userdm->set('posts', "posts + {$sourceinfo['posts']}", false); $userdm->set_ladder_usertitle_relative($sourceinfo['posts']); $userdm->set('reputation', "reputation + {$sourceinfo['reputation']} - " . $options['reputationdefault'], false); $userdm->set('lastvisit', "IF(lastvisit < {$sourceinfo['lastvisit']}, {$sourceinfo['lastvisit']}, lastvisit)", false); $userdm->set('lastactivity', "IF(lastactivity < {$sourceinfo['lastactivity']}, {$sourceinfo['lastactivity']}, lastactivity)", false); $userdm->set('lastpost', "IF(lastpost < {$sourceinfo['lastpost']}, {$sourceinfo['lastpost']}, lastpost)", false); $userdm->set('pmtotal', "pmtotal + {$sourceinfo['pmtotal']}", false); $userdm->set('pmunread', "pmunread + {$sourceinfo['pmunread']}", false); $userdm->set('gmmoderatedcount', "gmmoderatedcount + {$sourceinfo['gmmoderatedcount']}", false); if ($sourceinfo['joindate'] > 0) { // get the older join date, but only if we actually have a date $userdm->set('joindate', "IF(joindate > {$sourceinfo['joindate']}, {$sourceinfo['joindate']}, joindate)", false); } $userdm->set('ipoints', "ipoints + " . intval($sourceinfo['ipoints']), false); $userdm->set('warnings', "warnings + " . intval($sourceinfo['warnings']), false); $userdm->set('infractions', "infractions + " . intval($sourceinfo['infractions']), false); $assertor->assertQuery('user_insertuserlist', array('sourceuserid' => $sourceinfo['userid'], 'destuserid' => $destinfo['userid'])); $assertor->assertQuery('user_updateuserlist', array('sourceuserid' => $sourceinfo['userid'], 'destuserid' => $destinfo['userid'])); $myfriendcount = $assertor->getField('user_fetchuserlistcount', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_STORED, 'userid' => $destinfo['userid'])); $userdm->set('friendcount', $myfriendcount); $userdm->save(); unset($userdm); require_once DIR . '/includes/functions_databuild.php'; build_userlist($destinfo['userid']); // if the source user has infractions, then we need to update the infraction groups on the dest // easier to do it this way to make sure we get fresh info about the destination user if ($sourceinfo['ipoints']) { unset($usercache["{$destinfo['userid']}"]); $new_user = vB_User::fetchUserInfo($destinfo['userid']); $infractiongroups = array(); $groups = $assertor->assertQuery('user_fetchinfractiongroup', array()); foreach ($groups as $group) { $infractiongroups["{$group['usergroupid']}"]["{$group['pointlevel']}"][] = array('orusergroupid' => $group['orusergroupid'], 'override' => $group['override']); } $userdm = new vB_Datamanager_User(vB_DataManager_Constants::ERRTYPE_SILENT); $userdm->set_existing($new_user); $infractioninfo = vB_Library::instance('Content_Infraction')->fetchInfractionGroups($infractiongroups, $new_user['userid'], $new_user['ipoints'], $new_user['usergroupid']); $userdm->set('infractiongroupids', $infractioninfo['infractiongroupids']); $userdm->set('infractiongroupid', $infractioninfo['infractiongroupid']); $userdm->save(); unset($userdm); } // Update announcements $assertor->assertQuery('user_updateannouncement', array('sourceuserid' => $sourceinfo['userid'], 'destuserid' => $destinfo['userid'])); // Update Read Announcements $assertor->assertQuery('userInsertAnnouncementread', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_METHOD, 'sourceuserid' => $sourceinfo['userid'], 'destuserid' => $destinfo['userid'])); // Update Deletion Log $assertor->assertQuery('user_updatedeletionlog', array('sourceuserid' => $sourceinfo['userid'], 'destuserid' => $destinfo['userid'], 'destusername' => $destinfo['username'])); // Update Edit Log $assertor->assertQuery('user_updateeditlog', array('sourceuserid' => $sourceinfo['userid'], 'destuserid' => $destinfo['userid'], 'destusername' => $destinfo['username'])); // Update Edit Log $assertor->assertQuery('user_updatepostedithistory', array('sourceuserid' => $sourceinfo['userid'], 'destuserid' => $destinfo['userid'], 'destusername' => $destinfo['username'])); // Update Poll Votes - find any poll where we both voted // we need to remove the source user's vote $pollconflicts = array(); $polls = $assertor->assertQuery('user_fetchpollvote', array('sourceuserid' => $sourceinfo['userid'], 'destuserid' => $destinfo['userid'])); foreach ($polls as $poll) { $pollconflicts["{$poll['nodeid']}"] = $poll; } $assertor->assertQuery('user_updatepollvote', array('sourceuserid' => $sourceinfo['userid'], 'destuserid' => $destinfo['userid'])); if (!empty($pollconflicts)) { $assertor->assertQuery('user_deletepollvote', array('userid' => $sourceinfo['userid'])); // Polls that need to be rebuilt now foreach ($pollconflicts as $pollconflict) { vB_Api::instanceInternal('poll')->updatePollCache($pollconflict['nodeid']); $pollvotes = $assertor->assertQuery('user_fetchpollvote2', array('nodeid' => $pollconflict['nodeid'])); $lastvote = 0; foreach ($pollvotes as $pollvote) { if ($pollvote['votedate'] > $lastvote) { $lastvote = $pollvote['votedate']; } } // It appears that pollvote.votedate wasn't always set in the past so we could have votes with no datetime, hence the check on lastvote below $assertor->assertQuery('userUpdatePoll', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_METHOD, 'nodeid' => $pollconflict['nodeid'], 'lastvote' => $lastvote)); } } // Update User Notes $assertor->assertQuery('user_updateusernote', array('sourceuserid' => $sourceinfo['userid'], 'destuserid' => $destinfo['userid'])); $assertor->assertQuery('user_updateusernote2', array('sourceuserid' => $sourceinfo['userid'], 'destuserid' => $destinfo['userid'])); // Update Calendar Events $assertor->assertQuery('user_updateevent', array('sourceuserid' => $sourceinfo['userid'], 'destuserid' => $destinfo['userid'])); // Update Reputation Details $assertor->assertQuery('user_updatereputation', array('sourceuserid' => $sourceinfo['userid'], 'destuserid' => $destinfo['userid'])); $assertor->assertQuery('user_updatereputation2', array('sourceuserid' => $sourceinfo['userid'], 'destuserid' => $destinfo['userid'])); // Update infractions $assertor->assertQuery('user_updateinfraction', array('sourceuserid' => $sourceinfo['userid'], 'destuserid' => $destinfo['userid'])); $assertor->assertQuery('user_updateinfraction2', array('sourceuserid' => $sourceinfo['userid'], 'destuserid' => $destinfo['userid'])); // Update tags require_once DIR . '/includes/class_taggablecontent.php'; vB_Taggable_Content_Item::merge_users($sourceinfo['userid'], $destinfo['userid']); // Clear Group Transfers // $assertor->assertQuery('user_updatesocialgroup', array( // 'userid' => $sourceinfo['userid'], // )); // Delete requests if the dest user already has them $assertor->assertQuery('userDeleteUsergrouprequest', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_METHOD, 'sourceuserid' => $sourceinfo['userid'], 'destusergroupid' => $destinfo['usergroupid'], 'destmembergroupids' => $destinfo['membergroupids'])); // Convert remaining requests to dest user. $assertor->assertQuery('user_updateusergrouprequest', array('sourceuserid' => $sourceinfo['userid'], 'destuserid' => $destinfo['userid'])); // Paid Subscriptions $assertor->assertQuery('user_updatepaymentinfo', array('sourceuserid' => $sourceinfo['userid'], 'destuserid' => $destinfo['userid'])); // Move subscriptions over $assertor->assertQuery('user_updatesubscriptionlog', array('sourceuserid' => $sourceinfo['userid'], 'destuserid' => $destinfo['userid'])); $list = $remove = $update = array(); // Combine active subscriptions $subs = $assertor->assertQuery('user_fetchsubscriptionlog', array('userid' => $destinfo['userid'])); foreach ($subs as $sub) { $subscriptionid = $sub['subscriptionid']; $existing = $list[$subscriptionid]; if ($existing) { if ($sub['expirydate'] > $existing['expirydate']) { $remove[] = $existing['subscriptionlogid']; unset($update[$existing['subscriptionlogid']]); $list[$subscriptionid] = $sub; $update[$sub['subscriptionlogid']] = $sub['expirydate']; } else { $remove[] = $sub['subscriptionlogid']; } } else { $list[$subscriptionid] = $sub; } } if (!empty($remove)) { $assertor->assertQuery('user_deletesubscriptionlog', array('ids' => $remove)); } foreach ($update as $subscriptionlogid => $expirydate) { $assertor->assertQuery('user_updatesubscriptionlog2', array('expirydate' => $expirydate, 'subscriptionlogid' => $subscriptionlogid)); } //fix the names on any nodes that the user may be attached to. $assertor->assertQuery('vBForum:node', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_UPDATE, vB_dB_Query::CONDITIONS_KEY => array('userid' => $sourceinfo['userid']), 'authorname' => $destinfo['username'], 'userid' => $destinfo['userid'])); $assertor->assertQuery('vBForum:node', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_UPDATE, vB_dB_Query::CONDITIONS_KEY => array('lastauthorid' => $sourceinfo['userid']), 'lastcontentauthor' => $destinfo['username'], 'lastauthorid' => $destinfo['userid'])); // Remove remnants of source user $userdm = new vB_Datamanager_User(vB_DataManager_Constants::ERRTYPE_SILENT); $userdm->set_existing($sourceinfo); $userdm->delete(); unset($userdm); return true; }
$db->query_write("\r\n\t\tUPDATE IGNORE " . TABLE_PREFIX . "reputation\r\n\t\tSET whoadded = {$destinfo['userid']}\r\n\t\tWHERE whoadded = {$sourceinfo['userid']}\r\n\t"); // Update infractions $db->query_write("\r\n\t\tUPDATE " . TABLE_PREFIX . "infraction\r\n\t\tSET userid = {$destinfo['userid']}\r\n\t\tWHERE userid = {$sourceinfo['userid']}\r\n\t"); $db->query_write("\r\n\t\tUPDATE " . TABLE_PREFIX . "infraction\r\n\t\tSET whoadded = {$destinfo['userid']}\r\n\t\tWHERE whoadded = {$sourceinfo['userid']}\r\n\t"); // Update Private Messages $db->query_write("\r\n \t\tUPDATE " . TABLE_PREFIX . "pm\r\n\t\tSET userid = {$destinfo['userid']}\r\n\t\tWHERE userid = {$sourceinfo['userid']}\r\n\t\t\tAND folderid = -1\r\n\t"); $db->query_write("\r\n\t\tUPDATE " . TABLE_PREFIX . "pm\r\n\t\tSET userid = {$destinfo['userid']}, folderid = 0\r\n\t\tWHERE userid = {$sourceinfo['userid']}\r\n\t"); $db->query_write("\r\n\t\tUPDATE " . TABLE_PREFIX . "pmreceipt\r\n\t\tSET userid = {$destinfo['userid']}\r\n\t\tWHERE userid = {$sourceinfo['userid']}\r\n\t"); $db->query_write("\r\n\t\tUPDATE " . TABLE_PREFIX . "pmreceipt\r\n\t\tSET touserid = {$destinfo['userid']},\r\n\t\ttousername = '******'username']) . "'\r\n\t\tWHERE touserid = {$sourceinfo['userid']}\r\n\t"); $db->query_write("\r\n\t\tUPDATE " . TABLE_PREFIX . "pmtext\r\n\t\tSET fromuserid = {$destinfo['userid']},\r\n\t\tfromusername = '******'username']) . "'\r\n\t\tWHERE fromuserid = {$sourceinfo['userid']}\r\n\t"); // Update Visitor Messages $db->query_write("\r\n\t\tUPDATE " . TABLE_PREFIX . "visitormessage\r\n\t\tSET postuserid = {$destinfo['userid']},\r\n\t\t\tpostusername = '******'username']) . "'\r\n\t\tWHERE postuserid = {$sourceinfo['userid']}\r\n\t"); $db->query_write("\r\n\t\tUPDATE " . TABLE_PREFIX . "visitormessage\r\n\t\tSET userid = {$destinfo['userid']}\r\n\t\tWHERE userid = {$sourceinfo['userid']}\r\n\t"); // Update tags require_once 'includes/class_taggablecontent.php'; vB_Taggable_Content_Item::merge_users($sourceinfo['userid'], $destinfo['userid']); // Update Group Messages $db->query_write("\r\n\t\tUPDATE " . TABLE_PREFIX . "groupmessage\r\n\t\tSET postuserid = {$destinfo['userid']},\r\n\t\t\tpostusername = '******'username']) . "'\r\n\t\tWHERE postuserid = {$sourceinfo['userid']}\r\n\t"); // Clear Group Transfers $db->query_write("\r\n\t\tUPDATE " . TABLE_PREFIX . "socialgroup\r\n\t\tSET transferowner = 0\r\n\t\tWHERE transferowner = {$sourceinfo['userid']}\r\n\t"); // Delete requests if the dest user already has them $db->query_write("\r\n\t\tDELETE FROM " . TABLE_PREFIX . "usergrouprequest\r\n\t\tWHERE userid = {$sourceinfo['userid']} AND\r\n\t\t\t(usergroupid = {$destinfo['usergroupid']} " . ($destinfo['membergroupids'] != '' ? "OR usergroupid IN (0,{$destinfo['membergroupids']})" : '') . ")\r\n\t"); // Convert remaining requests to dest user. $db->query_write("\r\n\t\tUPDATE " . TABLE_PREFIX . "usergrouprequest\r\n\t\tSET userid = {$destinfo['userid']}\r\n\t\tWHERE userid = {$sourceinfo['userid']}\r\n\t"); $olduser = strlen($sourceinfo['username']); $newuser = strlen($destinfo['username']); $db->query_write("UPDATE " . TABLE_PREFIX . "pmtext\r\n\t\tSET touserarray = REPLACE(touserarray, 'i:{$sourceinfo['userid']};s:{$olduser}:\"" . $db->escape_string($sourceinfo['username']) . "\";','i:{$destinfo['userid']};s:{$newuser}:\"" . $db->escape_string($destinfo['username']) . "\";')\r\n\t"); $groups = array(); $groupids = array(); $memberships_dest = array(); $memberships_source = array();