]> git.mxchange.org Git - friendica.git/commitdiff
Fetch more comtact data from probing, remove duplicated contacts
authorMichael <heluecht@pirati.ca>
Fri, 12 Jul 2019 14:55:23 +0000 (14:55 +0000)
committerMichael <heluecht@pirati.ca>
Fri, 12 Jul 2019 14:55:23 +0000 (14:55 +0000)
src/Model/Contact.php
src/Network/Probe.php
src/Protocol/DFRN.php
src/Protocol/Diaspora.php

index 757508f261d86a50017419f38a781cec1fe822a6..17506a7d31dc6a5e256390cbdd2b0b6bd1ab626e 100644 (file)
@@ -1307,11 +1307,13 @@ class Contact extends BaseObject
 
                /// @todo Verify if we can't use Contact::getDetailsByUrl instead of the following
                // We first try the nurl (http://server.tld/nick), most common case
-               $contact = DBA::selectFirst('contact', ['id', 'avatar', 'updated', 'network'], ['nurl' => Strings::normaliseLink($url), 'uid' => $uid, 'deleted' => false]);
+               $fields = ['id', 'avatar', 'updated', 'network'];
+               $options = ['order' => ['id']];
+               $contact = DBA::selectFirst('contact', $fields, ['nurl' => Strings::normaliseLink($url), 'uid' => $uid, 'deleted' => false], $options);
 
                // Then the addr (nick@server.tld)
                if (!DBA::isResult($contact)) {
-                       $contact = DBA::selectFirst('contact', ['id', 'avatar', 'updated', 'network'], ['addr' => $url, 'uid' => $uid, 'deleted' => false]);
+                       $contact = DBA::selectFirst('contact', $fields, ['addr' => $url, 'uid' => $uid, 'deleted' => false], $options);
                }
 
                // Then the alias (which could be anything)
@@ -1319,7 +1321,7 @@ class Contact extends BaseObject
                        // The link could be provided as http although we stored it as https
                        $ssl_url = str_replace('http://', 'https://', $url);
                        $condition = ['`alias` IN (?, ?, ?) AND `uid` = ? AND NOT `deleted`', $url, Strings::normaliseLink($url), $ssl_url, $uid];
-                       $contact = DBA::selectFirst('contact', ['id', 'avatar', 'updated', 'network'], $condition);
+                       $contact = DBA::selectFirst('contact', $fields, $condition, $options);
                }
 
                if (DBA::isResult($contact)) {
@@ -1777,7 +1779,8 @@ class Contact extends BaseObject
        {
                DBA::update('contact', $fields, ['id' => $id]);
 
-               if ($uid != 0) {
+               // Search for duplicated contacts and get rid of them
+               if (self::handleDuplicates(Strings::normaliseLink($url), $uid, $id) || ($uid != 0)) {
                        return;
                }
 
@@ -1813,6 +1816,55 @@ class Contact extends BaseObject
                DBA::update('contact', $fields, $condition);
        }
 
+        /**
+        * @brief Helper function for "updateFromProbe". Remove duplicated contacts
+        *
+        * @param string  $nurl  Normalised contact url
+        * @param integer $uid   User id
+        * @param integer $id    Contact id of a duplicate
+        * @throws \Exception
+        */
+       private static function handleDuplicates($nurl, $uid, $id)
+       {
+               $condition = ['nurl' => $nurl, 'uid' => $uid, 'deleted' => false];
+               $count = DBA::count('contact', $condition);
+               if ($count <= 1) {
+                       return false;
+               }
+
+               $first_contact = DBA::selectFirst('contact', ['id'], $condition, ['order' => ['id']]);
+               if (!DBA::isResult($first_contact)) {
+                       // Shouldn't happen - so we handle it
+                       return false;
+               }
+
+               $first = $first_contact['id'];
+               Logger::info('Found duplicates', ['count' => $count, 'id' => $id, 'first' => $first, 'uid' => $uid, 'nurl' => $nurl, 'callstack' => System::callstack(20)]);
+               if ($uid != 0) {
+                       // Don't handle non public duplicates by now
+                       Logger::info('Not handling non public 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);
+               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]);
+
+                       // Remove the duplicate
+                       DBA::delete('contact', ['id' => $dup_id]);
+               }
+               Logger::info('Duplicates handled', ['uid' => $uid, 'nurl' => $nurl]);
+               return true;
+       }
+
        /**
         * @param integer $id      contact id
         * @param string  $network Optional network we are probing for
@@ -1829,11 +1881,11 @@ class Contact extends BaseObject
                 */
 
                // These fields aren't updated by this routine:
-               // 'location', 'about', 'keywords', 'gender', 'xmpp', 'unsearchable', 'sensitive'];
+               // 'xmpp', 'sensitive'
 
-               $fields = ['avatar', 'uid', 'name', 'nick', 'url', 'addr', 'batch', 'notify',
-                       'poll', 'request', 'confirm', 'poco', 'network', 'alias', 'baseurl',
-                       'forum', 'prv', 'contact-type'];
+               $fields = ['uid', 'avatar', 'name', 'nick', 'location', 'keywords', 'about', 'gender',
+                       'unsearchable', 'url', 'addr', 'batch', 'notify', 'poll', 'request', 'confirm', 'poco',
+                       'network', 'alias', 'baseurl', 'forum', 'prv', 'contact-type'];
                $contact = DBA::selectFirst('contact', $fields, ['id' => $id]);
                if (!DBA::isResult($contact)) {
                        return false;
@@ -1858,7 +1910,11 @@ class Contact extends BaseObject
                        return false;
                }
 
-               if (isset($ret['account-type'])) {
+               if (isset($ret['hide']) && is_bool($ret['hide'])) {
+                       $ret['unsearchable'] = $ret['hide'];
+               }
+
+               if (isset($ret['account-type']) && is_int($ret['account-type'])) {
                        $ret['forum'] = false;
                        $ret['prv'] = false;
                        $ret['contact-type'] = $ret['account-type'];
@@ -1873,11 +1929,12 @@ class Contact extends BaseObject
 
                $update = false;
 
-               // make sure to not overwrite existing values with blank entries
+               // make sure to not overwrite existing values with blank entries except some technical fields
+               $keep = ['batch', 'notify', 'poll', 'request', 'confirm', 'poco', 'baseurl'];
                foreach ($ret as $key => $val) {
                        if (!array_key_exists($key, $contact)) {
                                unset($ret[$key]);
-                       } elseif (($contact[$key] != '') && ($val == '') && !is_bool($ret[$key])) {
+                       } elseif (($contact[$key] != '') && ($val == '') && !is_bool($ret[$key]) && !in_array($key, $keep)) {
                                $ret[$key] = $contact[$key];
                        } elseif ($ret[$key] != $contact[$key]) {
                                $update = true;
@@ -1915,10 +1972,12 @@ class Contact extends BaseObject
                $id = self::getIdForURL($url);
 
                if (empty($id)) {
-                       return;
+                       return $id;
                }
 
                self::updateFromProbe($id, '', $force);
+
+               return $id;
        }
 
        /**
index 0094609b26fab1c9fa9b14d5f2b02c7f9345026e..c38c43c0902261bfaff771787765454e954a5621 100644 (file)
@@ -45,8 +45,8 @@ class Probe
         */
        private static function rearrangeData($data)
        {
-               $fields = ["name", "nick", "guid", "url", "addr", "alias", "photo",
-                               "account-type", "community", "keywords", "location", "about",
+               $fields = ["name", "nick", "guid", "url", "addr", "alias", "photo", "account-type",
+                               "community", "keywords", "location", "about", "gender", "hide",
                                "batch", "notify", "poll", "request", "confirm", "poco",
                                "following", "followers", "inbox", "outbox", "sharedinbox",
                                "priority", "network", "pubkey", "baseurl"];
@@ -351,6 +351,7 @@ class Probe
                        if (!empty($ap_profile) && empty($network) && (defaults($data, 'network', '') != Protocol::DFRN)) {
                                $data = $ap_profile;
                        } elseif (!empty($ap_profile)) {
+                               $ap_profile['batch'] = '';
                                $data = array_merge($ap_profile, $data);
                        }
                } else {
@@ -739,7 +740,7 @@ class Probe
                }
 
                if (!empty($json["tags"])) {
-                       $keywords = implode(" ", $json["tags"]);
+                       $keywords = implode(", ", $json["tags"]);
                        if ($keywords != "") {
                                $data["keywords"] = $keywords;
                        }
@@ -754,6 +755,10 @@ class Probe
                        $data["about"] = $json["about"];
                }
 
+               if (!empty($json["gender"])) {
+                       $data["gender"] = $json["gender"];
+               }
+
                if (!empty($json["key"])) {
                        $data["pubkey"] = $json["key"];
                }
@@ -778,6 +783,12 @@ class Probe
                        $data["poll"] = $json["dfrn-poll"];
                }
 
+               if (isset($json["hide"])) {
+                       $data["hide"] = (bool)$json["hide"];
+               } else {
+                       $data["hide"] = false;
+               }
+
                return $data;
        }
 
index 84c4affc70815d32724c49680c0ddd088934cb37..5fceab3264d7ab9cc70056c7db2486db4c991124 100644 (file)
@@ -1693,13 +1693,12 @@ class DFRN
                                'location' => $contact['location'], 'addr' => $contact['addr'], 'keywords' => $contact['keywords'],
                                'bdyear' => $contact['bdyear'], 'bd' => $contact['bd'], 'hidden' => $contact['hidden'],
                                'xmpp' => $contact['xmpp'], 'name-date' => DateTimeFormat::utc($contact['name-date']),
-                               'uri-date' => DateTimeFormat::utc($contact['uri-date'])];
+                               'unsearchable' => $contact['hidden'], 'uri-date' => DateTimeFormat::utc($contact['uri-date'])];
 
                        DBA::update('contact', $fields, ['id' => $contact['id'], 'network' => $contact['network']], $contact_old);
 
                        // Update the public contact. Don't set the "hidden" value, this is used differently for public contacts
                        unset($fields['hidden']);
-                       $fields['unsearchable'] = $hide;
                        $condition = ['uid' => 0, 'nurl' => Strings::normaliseLink($contact_old['url'])];
                        DBA::update('contact', $fields, $condition, true);
 
index 31d9efa18fe2d756510595fb6757cca9b7e62798..a264398efd4289016a96585538bb67c58ba07978 100644 (file)
@@ -2267,6 +2267,8 @@ class Diaspora
 
                DBA::update('contact', $fields, ['id' => $contact['id']]);
 
+               // @todo Update the public contact, then update the gcontact from that
+
                $gcontact = ["url" => $contact["url"], "network" => Protocol::DIASPORA, "generation" => 2,
                                        "photo" => $image_url, "name" => $name, "location" => $location,
                                        "about" => $about, "birthday" => $birthday, "gender" => $gender,