Issue 7559: Merge contact duplicates
This commit is contained in:
parent
b914900ff5
commit
7d50a086e0
3 changed files with 66 additions and 57 deletions
|
@ -1851,13 +1851,13 @@ class Contact extends BaseObject
|
||||||
*/
|
*/
|
||||||
private static function handleDuplicates($nurl, $uid, $id)
|
private static function handleDuplicates($nurl, $uid, $id)
|
||||||
{
|
{
|
||||||
$condition = ['nurl' => $nurl, 'uid' => $uid, 'deleted' => false];
|
$condition = ['nurl' => $nurl, 'uid' => $uid, 'deleted' => false, 'network' => Protocol::FEDERATED];
|
||||||
$count = DBA::count('contact', $condition);
|
$count = DBA::count('contact', $condition);
|
||||||
if ($count <= 1) {
|
if ($count <= 1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$first_contact = DBA::selectFirst('contact', ['id'], $condition, ['order' => ['id']]);
|
$first_contact = DBA::selectFirst('contact', ['id', 'network'], $condition, ['order' => ['id']]);
|
||||||
if (!DBA::isResult($first_contact)) {
|
if (!DBA::isResult($first_contact)) {
|
||||||
// Shouldn't happen - so we handle it
|
// Shouldn't happen - so we handle it
|
||||||
return false;
|
return false;
|
||||||
|
@ -1865,26 +1865,21 @@ class Contact extends BaseObject
|
||||||
|
|
||||||
$first = $first_contact['id'];
|
$first = $first_contact['id'];
|
||||||
Logger::info('Found duplicates', ['count' => $count, 'id' => $id, 'first' => $first, 'uid' => $uid, 'nurl' => $nurl]);
|
Logger::info('Found duplicates', ['count' => $count, 'id' => $id, 'first' => $first, 'uid' => $uid, 'nurl' => $nurl]);
|
||||||
if ($uid != 0) {
|
if (($uid != 0 && ($first_contact['network'] == Protocol::DFRN))) {
|
||||||
// Don't handle non public duplicates by now
|
// Don't handle non public DFRN duplicates by now (legacy DFRN is very special because of the key handling)
|
||||||
Logger::info('Not handling non public duplicate', ['uid' => $uid, 'nurl' => $nurl]);
|
Logger::info('Not handling non public DFRN duplicate', ['uid' => $uid, 'nurl' => $nurl]);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find all duplicates
|
// Find all duplicates
|
||||||
$condition = ["`nurl` = ? AND `uid` = ? AND `id` != ? AND NOT `self` AND NOT `deleted`", $nurl, $uid, $first];
|
$condition = ["`nurl` = ? AND `uid` = ? AND `id` != ? AND NOT `self` AND NOT `deleted`", $nurl, $uid, $first];
|
||||||
$duplicates = DBA::select('contact', ['id'], $condition);
|
$duplicates = DBA::select('contact', ['id', 'network'], $condition);
|
||||||
while ($duplicate = DBA::fetch($duplicates)) {
|
while ($duplicate = DBA::fetch($duplicates)) {
|
||||||
$dup_id = $duplicate['id'];
|
if (!in_array($duplicate['network'], Protocol::FEDERATED)) {
|
||||||
Logger::info('Handling duplicate', ['search' => $dup_id, 'replace' => $first]);
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Search and replace
|
Worker::add(PRIORITY_HIGH, 'MergeContact', $first, $duplicate['id'], $uid);
|
||||||
DBA::update('item', ['author-id' => $first], ['author-id' => $dup_id]);
|
|
||||||
DBA::update('item', ['owner-id' => $first], ['owner-id' => $dup_id]);
|
|
||||||
DBA::update('item', ['contact-id' => $first], ['contact-id' => $dup_id]);
|
|
||||||
|
|
||||||
// Remove the duplicate
|
|
||||||
DBA::delete('contact', ['id' => $dup_id]);
|
|
||||||
}
|
}
|
||||||
Logger::info('Duplicates handled', ['uid' => $uid, 'nurl' => $nurl]);
|
Logger::info('Duplicates handled', ['uid' => $uid, 'nurl' => $nurl]);
|
||||||
return true;
|
return true;
|
||||||
|
@ -1985,7 +1980,7 @@ class Contact extends BaseObject
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$update) {
|
if (!$update) {
|
||||||
if ($force && ($uid == 0)) {
|
if ($force) {
|
||||||
self::updateContact($id, $uid, $ret['url'], ['last-update' => $updated, 'success_update' => $updated]);
|
self::updateContact($id, $uid, $ret['url'], ['last-update' => $updated, 'success_update' => $updated]);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -2377,7 +2372,18 @@ class Contact extends BaseObject
|
||||||
$nick = $pub_contact['nick'];
|
$nick = $pub_contact['nick'];
|
||||||
$network = $pub_contact['network'];
|
$network = $pub_contact['network'];
|
||||||
|
|
||||||
|
// Ensure that we don't create a new contact when there already is one
|
||||||
|
$cid = self::getIdForURL($url, $importer['uid']);
|
||||||
|
if (!empty($cid)) {
|
||||||
|
$contact = DBA::selectFirst('contact', [], ['id' => $cid]);
|
||||||
|
}
|
||||||
|
|
||||||
if (!empty($contact)) {
|
if (!empty($contact)) {
|
||||||
|
if (!empty($contact['pending'])) {
|
||||||
|
Logger::info('Pending contact request already exists.', ['url' => $url, 'uid' => $importer['uid']]);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
// Contact is blocked at user-level
|
// Contact is blocked at user-level
|
||||||
if (!empty($contact['id']) && !empty($importer['id']) &&
|
if (!empty($contact['id']) && !empty($importer['id']) &&
|
||||||
self::isBlockedByUser($contact['id'], $importer['id'])) {
|
self::isBlockedByUser($contact['id'], $importer['id'])) {
|
||||||
|
|
|
@ -176,54 +176,16 @@ class Contact extends BaseModule
|
||||||
|
|
||||||
private static function updateContactFromProbe($contact_id)
|
private static function updateContactFromProbe($contact_id)
|
||||||
{
|
{
|
||||||
$contact = DBA::selectFirst('contact', ['uid', 'url', 'network'], ['id' => $contact_id, 'uid' => local_user(), 'deleted' => false]);
|
$contact = DBA::selectFirst('contact', ['url'], ['id' => $contact_id, 'uid' => local_user(), 'deleted' => false]);
|
||||||
if (!DBA::isResult($contact)) {
|
if (!DBA::isResult($contact)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$uid = $contact['uid'];
|
|
||||||
|
|
||||||
$data = Probe::uri($contact['url'], '', 0, false);
|
|
||||||
|
|
||||||
// 'Feed' or 'Unknown' is mostly a sign of communication problems
|
|
||||||
if ((in_array($data['network'], [Protocol::FEED, Protocol::PHANTOM])) && ($data['network'] != $contact['network'])) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$updatefields = ['name', 'nick', 'url', 'addr', 'batch', 'notify', 'poll', 'request', 'confirm', 'poco', 'network', 'alias'];
|
|
||||||
$fields = [];
|
|
||||||
|
|
||||||
if ($data['network'] == Protocol::OSTATUS) {
|
|
||||||
$result = Model\Contact::createFromProbe($uid, $data['url'], false);
|
|
||||||
|
|
||||||
if ($result['success']) {
|
|
||||||
$fields['subhub'] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($updatefields AS $field) {
|
|
||||||
if (!empty($data[$field])) {
|
|
||||||
$fields[$field] = $data[$field];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$fields['nurl'] = Strings::normaliseLink($data['url']);
|
|
||||||
|
|
||||||
if (!empty($data['priority'])) {
|
|
||||||
$fields['priority'] = intval($data['priority']);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($fields)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DBA::update('contact', $fields, ['id' => $contact_id, 'uid' => local_user()]);
|
|
||||||
|
|
||||||
// Update the entry in the contact table
|
// Update the entry in the contact table
|
||||||
Model\Contact::updateAvatar($data['photo'], local_user(), $contact_id, true);
|
Model\Contact::updateFromProbe($contact_id, '', true);
|
||||||
|
|
||||||
// Update the entry in the gcontact table
|
// Update the entry in the gcontact table
|
||||||
Model\GContact::updateFromProbe($data['url']);
|
Model\GContact::updateFromProbe($contact['url']);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function blockContact($contact_id)
|
private static function blockContact($contact_id)
|
||||||
|
|
41
src/Worker/MergeContact.php
Normal file
41
src/Worker/MergeContact.php
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file src/Worker/MergeContact.php
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Friendica\Worker;
|
||||||
|
|
||||||
|
use Friendica\Core\Logger;
|
||||||
|
use Friendica\Database\DBA;
|
||||||
|
|
||||||
|
class MergeContact
|
||||||
|
{
|
||||||
|
public static function execute($first, $dup_id, $uid)
|
||||||
|
{
|
||||||
|
if (empty($first) || empty($dup_id) || ($first == $dup_id)) {
|
||||||
|
// Invalid request
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger::info('Handling duplicate', ['search' => $dup_id, 'replace' => $first]);
|
||||||
|
|
||||||
|
// Search and replace
|
||||||
|
DBA::update('item', ['contact-id' => $first], ['contact-id' => $dup_id]);
|
||||||
|
DBA::update('thread', ['contact-id' => $first], ['contact-id' => $dup_id]);
|
||||||
|
DBA::update('mail', ['contact-id' => $first], ['contact-id' => $dup_id]);
|
||||||
|
DBA::update('photo', ['contact-id' => $first], ['contact-id' => $dup_id]);
|
||||||
|
DBA::update('event', ['cid' => $first], ['cid' => $dup_id]);
|
||||||
|
if ($uid == 0) {
|
||||||
|
DBA::update('item', ['author-id' => $first], ['author-id' => $dup_id]);
|
||||||
|
DBA::update('item', ['owner-id' => $first], ['owner-id' => $dup_id]);
|
||||||
|
DBA::update('thread', ['author-id' => $first], ['author-id' => $dup_id]);
|
||||||
|
DBA::update('thread', ['owner-id' => $first], ['owner-id' => $dup_id]);
|
||||||
|
} else {
|
||||||
|
/// @todo Check if some other data needs to be adjusted as well, possibly the "rel" status?
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the duplicate
|
||||||
|
DBA::delete('contact', ['id' => $dup_id]);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue