Merge pull request #7582 from annando/contact-dba
Avoid and remove duplicated contact entries
This commit is contained in:
commit
0c876db30f
3 changed files with 76 additions and 13 deletions
|
@ -37,6 +37,9 @@ class PostUpdate
|
||||||
if (!self::update1297()) {
|
if (!self::update1297()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (!self::update1322()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -414,6 +417,40 @@ class PostUpdate
|
||||||
|
|
||||||
Logger::info('Done');
|
Logger::info('Done');
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Remove contact duplicates
|
||||||
|
*
|
||||||
|
* @return bool "true" when the job is done
|
||||||
|
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||||
|
*/
|
||||||
|
private static function update1322()
|
||||||
|
{
|
||||||
|
// Was the script completed?
|
||||||
|
if (Config::get('system', 'post_update_version') >= 1322) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger::info('Start');
|
||||||
|
|
||||||
|
$contacts = DBA::p("SELECT `nurl`, `uid` FROM `contact`
|
||||||
|
WHERE EXISTS (SELECT `nurl` FROM `contact` AS `c2`
|
||||||
|
WHERE `c2`.`nurl` = `contact`.`nurl` AND `c2`.`id` != `contact`.`id` AND `c2`.`uid` = `contact`.`uid` AND `c2`.`network` IN (?, ?, ?) AND NOT `deleted`)
|
||||||
|
AND (`network` IN (?, ?, ?) OR (`uid` = ?)) AND NOT `deleted` GROUP BY `nurl`, `uid`",
|
||||||
|
Protocol::DIASPORA, Protocol::OSTATUS, Protocol::ACTIVITYPUB,
|
||||||
|
Protocol::DIASPORA, Protocol::OSTATUS, Protocol::ACTIVITYPUB, 0);
|
||||||
|
|
||||||
|
while ($contact = DBA::fetch($contacts)) {
|
||||||
|
Logger::info('Remove duplicates', ['nurl' => $contact['nurl'], 'uid' => $contact['uid']]);
|
||||||
|
Contact::removeDuplicates($contact['nurl'], $contact['uid']);
|
||||||
|
}
|
||||||
|
|
||||||
|
DBA::close($contact);
|
||||||
|
Config::set('system', 'post_update_version', 1322);
|
||||||
|
|
||||||
|
Logger::info('Done');
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -136,6 +136,31 @@ class Contact extends BaseObject
|
||||||
return $contact;
|
return $contact;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert a row into the contact table
|
||||||
|
* Important: You can't use DBA::lastInsertId() after this call since it will be set to 0.
|
||||||
|
*
|
||||||
|
* @param array $fields field array
|
||||||
|
* @param bool $on_duplicate_update Do an update on a duplicate entry
|
||||||
|
*
|
||||||
|
* @return boolean was the insert successful?
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
public static function insert(array $fields, bool $on_duplicate_update = false)
|
||||||
|
{
|
||||||
|
$ret = DBA::insert('contact', $fields, $on_duplicate_update);
|
||||||
|
$contact = DBA::selectFirst('contact', ['nurl', 'uid'], ['id' => DBA::lastInsertId()]);
|
||||||
|
if (!DBA::isResult($contact)) {
|
||||||
|
// Shouldn't happen
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search for duplicated contacts and get rid of them
|
||||||
|
self::removeDuplicates($contact['nurl'], $contact['uid']);
|
||||||
|
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param integer $id Contact ID
|
* @param integer $id Contact ID
|
||||||
* @param array $fields Array of selected fields, empty for all
|
* @param array $fields Array of selected fields, empty for all
|
||||||
|
@ -878,6 +903,13 @@ class Contact extends BaseObject
|
||||||
*/
|
*/
|
||||||
public static function unmarkForArchival(array $contact)
|
public static function unmarkForArchival(array $contact)
|
||||||
{
|
{
|
||||||
|
// Always unarchive the relay contact entry
|
||||||
|
if (!empty($contact['batch'])) {
|
||||||
|
$fields = ['term-date' => DBA::NULL_DATETIME, 'archive' => false];
|
||||||
|
$condition = ['batch' => $contact['batch'], 'contact-type' => self::TYPE_RELAY];
|
||||||
|
DBA::update('contact', $fields, $condition);
|
||||||
|
}
|
||||||
|
|
||||||
$condition = ['`id` = ? AND (`term-date` > ? OR `archive`)', $contact['id'], DBA::NULL_DATETIME];
|
$condition = ['`id` = ? AND (`term-date` > ? OR `archive`)', $contact['id'], DBA::NULL_DATETIME];
|
||||||
$exists = DBA::exists('contact', $condition);
|
$exists = DBA::exists('contact', $condition);
|
||||||
|
|
||||||
|
@ -901,11 +933,6 @@ class Contact extends BaseObject
|
||||||
DBA::update('contact', $fields, ['id' => $contact['id']]);
|
DBA::update('contact', $fields, ['id' => $contact['id']]);
|
||||||
DBA::update('contact', $fields, ['nurl' => Strings::normaliseLink($contact['url']), 'self' => false]);
|
DBA::update('contact', $fields, ['nurl' => Strings::normaliseLink($contact['url']), 'self' => false]);
|
||||||
GContact::updateFromPublicContactURL($contact['url']);
|
GContact::updateFromPublicContactURL($contact['url']);
|
||||||
|
|
||||||
if (!empty($contact['batch'])) {
|
|
||||||
$condition = ['batch' => $contact['batch'], 'contact-type' => self::TYPE_RELAY];
|
|
||||||
DBA::update('contact', $fields, $condition);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1488,7 +1515,7 @@ class Contact extends BaseObject
|
||||||
if (!DBA::isResult($contact)) {
|
if (!DBA::isResult($contact)) {
|
||||||
Logger::info('Create new contact', $fields);
|
Logger::info('Create new contact', $fields);
|
||||||
|
|
||||||
DBA::insert('contact', $fields);
|
self::insert($fields);
|
||||||
|
|
||||||
// We intentionally aren't using lastInsertId here. There is a chance for duplicates.
|
// We intentionally aren't using lastInsertId here. There is a chance for duplicates.
|
||||||
$contact = DBA::selectFirst('contact', ['id'], $condition, ['order' => ['id']]);
|
$contact = DBA::selectFirst('contact', ['id'], $condition, ['order' => ['id']]);
|
||||||
|
@ -1853,7 +1880,7 @@ class Contact extends BaseObject
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search for duplicated contacts and get rid of them
|
// Search for duplicated contacts and get rid of them
|
||||||
if (self::handleDuplicates(Strings::normaliseLink($url), $uid, $id) || ($uid != 0)) {
|
if (self::removeDuplicates(Strings::normaliseLink($url), $uid) || ($uid != 0)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1895,15 +1922,14 @@ class Contact extends BaseObject
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Helper function for "updateFromProbe". Remove duplicated contacts
|
* @brief Remove duplicated contacts
|
||||||
*
|
*
|
||||||
* @param string $nurl Normalised contact url
|
* @param string $nurl Normalised contact url
|
||||||
* @param integer $uid User id
|
* @param integer $uid User id
|
||||||
* @param integer $id Contact id of a duplicate
|
|
||||||
* @return boolean
|
* @return boolean
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
private static function handleDuplicates($nurl, $uid, $id)
|
public static function removeDuplicates(string $nurl, int $uid)
|
||||||
{
|
{
|
||||||
$condition = ['nurl' => $nurl, 'uid' => $uid, 'deleted' => false, 'network' => Protocol::FEDERATED];
|
$condition = ['nurl' => $nurl, 'uid' => $uid, 'deleted' => false, 'network' => Protocol::FEDERATED];
|
||||||
$count = DBA::count('contact', $condition);
|
$count = DBA::count('contact', $condition);
|
||||||
|
@ -1918,7 +1944,7 @@ 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, 'first' => $first, 'uid' => $uid, 'nurl' => $nurl]);
|
||||||
if (($uid != 0 && ($first_contact['network'] == Protocol::DFRN))) {
|
if (($uid != 0 && ($first_contact['network'] == Protocol::DFRN))) {
|
||||||
// Don't handle non public DFRN duplicates by now (legacy DFRN is very special because of the key handling)
|
// 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 DFRN duplicate', ['uid' => $uid, 'nurl' => $nurl]);
|
Logger::info('Not handling non public DFRN duplicate', ['uid' => $uid, 'nurl' => $nurl]);
|
||||||
|
@ -2265,7 +2291,7 @@ class Contact extends BaseObject
|
||||||
$new_relation = (in_array($protocol, [Protocol::MAIL]) ? self::FRIEND : self::SHARING);
|
$new_relation = (in_array($protocol, [Protocol::MAIL]) ? self::FRIEND : self::SHARING);
|
||||||
|
|
||||||
// create contact record
|
// create contact record
|
||||||
DBA::insert('contact', [
|
self::insert([
|
||||||
'uid' => $uid,
|
'uid' => $uid,
|
||||||
'created' => DateTimeFormat::utcNow(),
|
'created' => DateTimeFormat::utcNow(),
|
||||||
'url' => $ret['url'],
|
'url' => $ret['url'],
|
||||||
|
|
|
@ -200,7 +200,7 @@ class Diaspora
|
||||||
DBA::update('contact', $fields, $condition, $old);
|
DBA::update('contact', $fields, $condition, $old);
|
||||||
} else {
|
} else {
|
||||||
Logger::info('Create relay contact', ['fields' => $fields]);
|
Logger::info('Create relay contact', ['fields' => $fields]);
|
||||||
DBA::insert('contact', $fields);
|
Contact::insert($fields);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue