]> git.mxchange.org Git - friendica.git/commitdiff
Merge pull request #7582 from annando/contact-dba
authorHypolite Petovan <hypolite@mrpetovan.com>
Fri, 30 Aug 2019 07:36:40 +0000 (03:36 -0400)
committerGitHub <noreply@github.com>
Fri, 30 Aug 2019 07:36:40 +0000 (03:36 -0400)
Avoid and remove duplicated contact entries

src/Database/PostUpdate.php
src/Model/Contact.php
src/Protocol/Diaspora.php

index acafea900c78fb62dafd7ef4e8e7fd4ff0b2edaf..885c9eea013d3b81a66999dc235fcc74ed52fa2c 100644 (file)
@@ -37,6 +37,9 @@ class PostUpdate
                if (!self::update1297()) {
                        return false;
                }
+               if (!self::update1322()) {
+                       return false;
+               }
 
                return true;
        }
@@ -414,6 +417,40 @@ class PostUpdate
 
                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;
        }
 }
index fdcef6f36a40aceaeddc39520d3177f3eb6eedbd..b18ebc22d6391272e35da6b8d66d047202c23693 100644 (file)
@@ -136,6 +136,31 @@ class Contact extends BaseObject
                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 array   $fields Array of selected fields, empty for all
@@ -878,6 +903,13 @@ class Contact extends BaseObject
         */
        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];
                $exists = DBA::exists('contact', $condition);
 
@@ -901,11 +933,6 @@ class Contact extends BaseObject
                DBA::update('contact', $fields, ['id' => $contact['id']]);
                DBA::update('contact', $fields, ['nurl' => Strings::normaliseLink($contact['url']), 'self' => false]);
                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)) {
                                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.
                                $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
-               if (self::handleDuplicates(Strings::normaliseLink($url), $uid, $id) || ($uid != 0)) {
+               if (self::removeDuplicates(Strings::normaliseLink($url), $uid) || ($uid != 0)) {
                        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 integer $uid   User id
-        * @param integer $id    Contact id of a duplicate
         * @return boolean
         * @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];
                $count = DBA::count('contact', $condition);
@@ -1918,7 +1944,7 @@ class Contact extends BaseObject
                }
 
                $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))) {
                        // 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]);
@@ -2265,7 +2291,7 @@ class Contact extends BaseObject
                        $new_relation = (in_array($protocol, [Protocol::MAIL]) ? self::FRIEND : self::SHARING);
 
                        // create contact record
-                       DBA::insert('contact', [
+                       self::insert([
                                'uid'     => $uid,
                                'created' => DateTimeFormat::utcNow(),
                                'url'     => $ret['url'],
index d578ba4545264085a265dd6ac3f574d721547707..b694ab9172109d1363d51190a860c8a8fea35149 100644 (file)
@@ -200,7 +200,7 @@ class Diaspora
                        DBA::update('contact', $fields, $condition, $old);
                } else {
                        Logger::info('Create relay contact', ['fields' => $fields]);
-                       DBA::insert('contact', $fields);
+                       Contact::insert($fields);
                }
        }