]> git.mxchange.org Git - friendica.git/commitdiff
Issue 7559: Merge contact duplicates
authorMichael <heluecht@pirati.ca>
Mon, 26 Aug 2019 15:51:56 +0000 (15:51 +0000)
committerMichael <heluecht@pirati.ca>
Mon, 26 Aug 2019 15:51:56 +0000 (15:51 +0000)
src/Model/Contact.php
src/Module/Contact.php
src/Worker/MergeContact.php [new file with mode: 0644]

index df3efa0c57036567144ddf536b707e0a9ed0a6c7..6f9ee4cdb6d9f4aa2bf508d83af596d2581f7311 100644 (file)
@@ -1851,13 +1851,13 @@ class Contact extends BaseObject
         */
        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);
                if ($count <= 1) {
                        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)) {
                        // Shouldn't happen - so we handle it
                        return false;
@@ -1865,26 +1865,21 @@ class Contact extends BaseObject
 
                $first = $first_contact['id'];
                Logger::info('Found duplicates', ['count' => $count, 'id' => $id, 'first' => $first, 'uid' => $uid, 'nurl' => $nurl]);
-               if ($uid != 0) {
-                       // Don't handle non public duplicates by now
-                       Logger::info('Not handling non public duplicate', ['uid' => $uid, 'nurl' => $nurl]);
+               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)
+                       Logger::info('Not handling non public DFRN duplicate', ['uid' => $uid, 'nurl' => $nurl]);
                        return false;
                }
 
                // Find all duplicates
                $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)) {
-                       $dup_id = $duplicate['id'];
-                       Logger::info('Handling duplicate', ['search' => $dup_id, 'replace' => $first]);
-
-                       // Search and replace
-                       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]);
+                       if (!in_array($duplicate['network'], Protocol::FEDERATED)) {
+                               continue;
+                       }
 
-                       // Remove the duplicate
-                       DBA::delete('contact', ['id' => $dup_id]);
+                       Worker::add(PRIORITY_HIGH, 'MergeContact', $first, $duplicate['id'], $uid);
                }
                Logger::info('Duplicates handled', ['uid' => $uid, 'nurl' => $nurl]);
                return true;
@@ -1985,7 +1980,7 @@ class Contact extends BaseObject
                }
 
                if (!$update) {
-                       if ($force && ($uid == 0)) {
+                       if ($force) {
                                self::updateContact($id, $uid, $ret['url'], ['last-update' => $updated, 'success_update' => $updated]);
                        }
                        return true;
@@ -2377,7 +2372,18 @@ class Contact extends BaseObject
                $nick = $pub_contact['nick'];
                $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['pending'])) {
+                               Logger::info('Pending contact request already exists.', ['url' => $url, 'uid' => $importer['uid']]);
+                               return null;
+                       }
+
                        // Contact is blocked at user-level
                        if (!empty($contact['id']) && !empty($importer['id']) &&
                                self::isBlockedByUser($contact['id'], $importer['id'])) {
index 04156daba9276b10d660dfd5a60f88a5b71d2ecd..198496a0eb61f6bf055f4e765eed30743d52b419 100644 (file)
@@ -176,54 +176,16 @@ class Contact extends BaseModule
 
        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)) {
                        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
-               Model\Contact::updateAvatar($data['photo'], local_user(), $contact_id, true);
+               Model\Contact::updateFromProbe($contact_id, '', true);
 
                // Update the entry in the gcontact table
-               Model\GContact::updateFromProbe($data['url']);
+               Model\GContact::updateFromProbe($contact['url']);
        }
 
        private static function blockContact($contact_id)
diff --git a/src/Worker/MergeContact.php b/src/Worker/MergeContact.php
new file mode 100644 (file)
index 0000000..a5e28e5
--- /dev/null
@@ -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]);
+       }
+}