]> git.mxchange.org Git - friendica.git/blobdiff - src/Model/GContact.php
Remove obsolete mod/lockview.php file
[friendica.git] / src / Model / GContact.php
index 6401c8baab141b49f3e08a62ad0a028a57d83ac2..ec53133c941ba040461a4f35ed2154d1efd14efe 100644 (file)
@@ -1,18 +1,34 @@
 <?php
 /**
- * @file src/Model/GlobalContact.php
- * This file includes the GlobalContact class with directory related functions
+ * @copyright Copyright (C) 2020, Friendica
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
  */
+
 namespace Friendica\Model;
 
 use DOMDocument;
 use DOMXPath;
 use Exception;
-use Friendica\Core\Config;
 use Friendica\Core\Logger;
 use Friendica\Core\Protocol;
-use Friendica\Core\System;
 use Friendica\Core\Search;
+use Friendica\Core\System;
+use Friendica\Core\Worker;
 use Friendica\Database\DBA;
 use Friendica\DI;
 use Friendica\Network\Probe;
@@ -43,13 +59,13 @@ class GContact
                }
 
                // check supported networks
-               if (Config::get('system', 'diaspora_enabled')) {
+               if (DI::config()->get('system', 'diaspora_enabled')) {
                        $diaspora = Protocol::DIASPORA;
                } else {
                        $diaspora = Protocol::DFRN;
                }
 
-               if (!Config::get('system', 'ostatus_disabled')) {
+               if (!DI::config()->get('system', 'ostatus_disabled')) {
                        $ostatus = Protocol::OSTATUS;
                } else {
                        $ostatus = Protocol::DFRN;
@@ -66,7 +82,7 @@ class GContact
 
                $results = DBA::p("SELECT `nurl` FROM `gcontact`
                        WHERE NOT `hide` AND `network` IN (?, ?, ?, ?) AND
-                               ((`last_contact` >= `last_failure`) OR (`updated` >= `last_failure`)) AND
+                               NOT `failed` AND
                                (`addr` LIKE ? OR `name` LIKE ? OR `nick` LIKE ?) $extra_sql
                                GROUP BY `nurl` ORDER BY `nurl` DESC LIMIT 1000",
                        Protocol::DFRN, Protocol::ACTIVITYPUB, $ostatus, $diaspora, $search, $search, $search
@@ -78,12 +94,13 @@ class GContact
 
                        // Ignore results that look strange.
                        // For historic reasons the gcontact table does contain some garbage.
-                       if (!empty($urlparts['query']) || !empty($urlparts['fragment'])) {
+                       if (empty($result['nurl']) || !empty($urlparts['query']) || !empty($urlparts['fragment'])) {
                                continue;
                        }
 
-                       $gcontacts[] = Contact::getDetailsByURL($result['nurl'], local_user());
+                       $gcontacts[] = Contact::getByURLForUser($result['nurl'], local_user());
                }
+               DBA::close($results);
                return $gcontacts;
        }
 
@@ -200,9 +217,8 @@ class GContact
                                throw new Exception('Probing for URL ' . $gcontact['url'] . ' failed');
                        }
 
-                       $orig_profile = $gcontact['url'];
-
                        $gcontact['server_url'] = $data['baseurl'];
+                       $gcontact['failed'] = false;
 
                        $gcontact = array_merge($gcontact, $data);
                }
@@ -245,8 +261,7 @@ class GContact
                        "SELECT count(*) as `total`
                        FROM `glink` INNER JOIN `gcontact` on `glink`.`gcid` = `gcontact`.`id`
                        WHERE `glink`.`cid` = %d AND `glink`.`uid` = %d AND
-                       ((`gcontact`.`last_contact` >= `gcontact`.`last_failure`) OR
-                       (`gcontact`.`updated` >= `gcontact`.`last_failure`))
+                       NOT `gcontact`.`failed`
                        AND `gcontact`.`nurl` IN (select nurl from contact where uid = %d and self = 0 and blocked = 0 and hidden = 0 and id != %d) ",
                        intval($cid),
                        intval($uid),
@@ -309,7 +324,7 @@ class GContact
                        WHERE `glink`.`cid` = %d and `glink`.`uid` = %d
                                AND `contact`.`uid` = %d AND `contact`.`self` = 0 AND `contact`.`blocked` = 0
                                AND `contact`.`hidden` = 0 AND `contact`.`id` != %d
-                               AND ((`gcontact`.`last_contact` >= `gcontact`.`last_failure`) OR (`gcontact`.`updated` >= `gcontact`.`last_failure`))
+                               AND NOT `gcontact`.`failed`
                                $sql_extra LIMIT %d, %d",
                        intval($cid),
                        intval($uid),
@@ -368,7 +383,7 @@ class GContact
                        "SELECT count(*) as `total`
                        FROM `glink` INNER JOIN `gcontact` on `glink`.`gcid` = `gcontact`.`id`
                        where `glink`.`cid` = %d and `glink`.`uid` = %d AND
-                       ((`gcontact`.`last_contact` >= `gcontact`.`last_failure`) OR (`gcontact`.`updated` >= `gcontact`.`last_failure`))",
+                       NOT `gcontact`.`failed`",
                        intval($cid),
                        intval($uid)
                );
@@ -396,7 +411,7 @@ class GContact
                        INNER JOIN `gcontact` on `glink`.`gcid` = `gcontact`.`id`
                        LEFT JOIN `contact` ON `contact`.`nurl` = `gcontact`.`nurl` AND `contact`.`uid` = %d
                        WHERE `glink`.`cid` = %d AND `glink`.`uid` = %d AND
-                       ((`gcontact`.`last_contact` >= `gcontact`.`last_failure`) OR (`gcontact`.`updated` >= `gcontact`.`last_failure`))
+                       NOT `gcontact`.`failed`
                        ORDER BY `gcontact`.`name` ASC LIMIT %d, %d ",
                        intval($uid),
                        intval($cid),
@@ -424,11 +439,11 @@ class GContact
 
                $network = [Protocol::DFRN, Protocol::ACTIVITYPUB];
 
-               if (Config::get('system', 'diaspora_enabled')) {
+               if (DI::config()->get('system', 'diaspora_enabled')) {
                        $network[] = Protocol::DIASPORA;
                }
 
-               if (!Config::get('system', 'ostatus_disabled')) {
+               if (!DI::config()->get('system', 'ostatus_disabled')) {
                        $network[] = Protocol::OSTATUS;
                }
 
@@ -443,7 +458,7 @@ class GContact
                        AND NOT `gcontact`.`name` IN (SELECT `name` FROM `contact` WHERE `uid` = %d)
                        AND NOT `gcontact`.`id` IN (SELECT `gcid` FROM `gcign` WHERE `uid` = %d)
                        AND `gcontact`.`updated` >= '%s' AND NOT `gcontact`.`hide`
-                       AND `gcontact`.`last_contact` >= `gcontact`.`last_failure`
+                       AND NOT `gcontact`.`failed`
                        AND `gcontact`.`network` IN (%s)
                        GROUP BY `glink`.`gcid` ORDER BY `gcontact`.`updated` DESC,`total` DESC LIMIT %d, %d",
                        intval($uid),
@@ -467,7 +482,7 @@ class GContact
                        AND NOT `gcontact`.`name` IN (SELECT `name` FROM `contact` WHERE `uid` = %d)
                        AND NOT `gcontact`.`id` IN (SELECT `gcid` FROM `gcign` WHERE `uid` = %d)
                        AND `gcontact`.`updated` >= '%s'
-                       AND `gcontact`.`last_contact` >= `gcontact`.`last_failure`
+                       AND NOT `gcontact`.`failed`
                        AND `gcontact`.`network` IN (%s)
                        ORDER BY rand() LIMIT %d, %d",
                        intval($uid),
@@ -508,8 +523,8 @@ class GContact
 
                $done[] = DI::baseUrl() . '/poco';
 
-               if (strlen(Config::get('system', 'directory'))) {
-                       $x = Network::fetchUrl(Search::getGlobalDirectory() . '/pubsites');
+               if (strlen(DI::config()->get('system', 'directory'))) {
+                       $x = DI::httpRequest()->fetch(Search::getGlobalDirectory() . '/pubsites');
                        if (!empty($x)) {
                                $j = json_decode($x);
                                if (!empty($j->entries)) {
@@ -534,6 +549,7 @@ class GContact
                                PortableContact::loadWorker(0, 0, 0, $base);
                        }
                }
+               DBA::close($contacts);
        }
 
        /**
@@ -580,8 +596,6 @@ class GContact
         */
        public static function getId($contact)
        {
-               $gcontact_id = 0;
-
                if (empty($contact['network'])) {
                        Logger::notice('Empty network', ['url' => $contact['url'], 'callstack' => System::callstack()]);
                        return false;
@@ -596,42 +610,37 @@ class GContact
                        $contact['network'] = Protocol::OSTATUS;
                }
 
-               // All new contacts are hidden by default
-               if (!isset($contact['hide'])) {
-                       $contact['hide'] = true;
-               }
-
                // Remove unwanted parts from the contact url (e.g. '?zrl=...')
                if (in_array($contact['network'], Protocol::FEDERATED)) {
                        $contact['url'] = self::cleanContactUrl($contact['url']);
                }
 
-               DBA::lock('gcontact');
-               $fields = ['id', 'last_contact', 'last_failure', 'network'];
-               $gcnt = DBA::selectFirst('gcontact', $fields, ['nurl' => Strings::normaliseLink($contact['url'])]);
-               if (DBA::isResult($gcnt)) {
-                       $gcontact_id = $gcnt['id'];
-               } else {
-                       $contact['location'] = $contact['location'] ?? '';
-                       $contact['about'] = $contact['about'] ?? '';
-                       $contact['generation'] = $contact['generation'] ?? 0;
+               $condition = ['nurl' => Strings::normaliseLink($contact['url'])];
+               $gcontact = DBA::selectFirst('gcontact', ['id'], $condition, ['order' => ['id']]);
+               if (DBA::isResult($gcontact)) {
+                       return $gcontact['id'];
+               }
 
-                       $fields = ['name' => $contact['name'], 'nick' => $contact['nick'] ?? '', 'addr' => $contact['addr'] ?? '', 'network' => $contact['network'],
-                               'url' => $contact['url'], 'nurl' => Strings::normaliseLink($contact['url']), 'photo' => $contact['photo'],
-                               'created' => DateTimeFormat::utcNow(), 'updated' => DateTimeFormat::utcNow(), 'location' => $contact['location'],
-                               'about' => $contact['about'], 'hide' => $contact['hide'], 'generation' => $contact['generation']];
+               $contact['location'] = $contact['location'] ?? '';
+               $contact['about'] = $contact['about'] ?? '';
+               $contact['generation'] = $contact['generation'] ?? 0;
+               $contact['hide'] = $contact['hide'] ?? true;
 
-                       DBA::insert('gcontact', $fields);
+               $fields = ['name' => $contact['name'], 'nick' => $contact['nick'] ?? '', 'addr' => $contact['addr'] ?? '', 'network' => $contact['network'],
+                       'url' => $contact['url'], 'nurl' => Strings::normaliseLink($contact['url']), 'photo' => $contact['photo'],
+                       'created' => DateTimeFormat::utcNow(), 'updated' => DateTimeFormat::utcNow(), 'location' => $contact['location'],
+                       'about' => $contact['about'], 'hide' => $contact['hide'], 'generation' => $contact['generation'], 'failed' => false];
 
-                       $condition = ['nurl' => Strings::normaliseLink($contact['url'])];
-                       $cnt = DBA::selectFirst('gcontact', ['id', 'network'], $condition, ['order' => ['id']]);
-                       if (DBA::isResult($cnt)) {
-                               $gcontact_id = $cnt['id'];
-                       }
-               }
-               DBA::unlock();
+               DBA::insert('gcontact', $fields);
 
-               return $gcontact_id;
+               // We intentionally aren't using lastInsertId here. There is a chance for duplicates.
+               $gcontact = DBA::selectFirst('gcontact', ['id'], $condition, ['order' => ['id']]);
+               if (!DBA::isResult($gcontact)) {
+                       Logger::info('GContact creation failed', $fields);
+                       // Shouldn't happen
+                       return 0;
+               }
+               return $gcontact['id'];
        }
 
        /**
@@ -659,7 +668,7 @@ class GContact
                }
 
                $public_contact = DBA::selectFirst('gcontact', [
-                       'name', 'nick', 'photo', 'location', 'about', 'addr', 'generation', 'birthday', 'gender', 'keywords',
+                       'name', 'nick', 'photo', 'location', 'about', 'addr', 'generation', 'birthday', 'keywords', 'gsid', 'failed',
                        'contact-type', 'hide', 'nsfw', 'network', 'alias', 'notify', 'server_url', 'connect', 'updated', 'url'
                ], ['id' => $gcontact_id]);
 
@@ -721,6 +730,10 @@ class GContact
                        $contact['server_url'] = Strings::normaliseLink($contact['server_url']);
                }
 
+               if (!empty($contact['server_url']) && empty($contact['gsid'])) {
+                       $contact['gsid'] = GServer::getID($contact['server_url']);
+               }
+
                if (empty($contact['addr']) && !empty($contact['server_url']) && !empty($contact['nick'])) {
                        $hostname = str_replace('http://', '', $contact['server_url']);
                        $contact['addr'] = $contact['nick'] . '@' . $hostname;
@@ -754,13 +767,14 @@ class GContact
                                'photo' => $contact['photo'], 'name' => $contact['name'],
                                'nick' => $contact['nick'], 'addr' => $contact['addr'],
                                'network' => $contact['network'], 'birthday' => $contact['birthday'],
-                               'gender' => $contact['gender'], 'keywords' => $contact['keywords'],
+                               'keywords' => $contact['keywords'],
                                'hide' => $contact['hide'], 'nsfw' => $contact['nsfw'],
                                'contact-type' => $contact['contact-type'], 'alias' => $contact['alias'],
                                'notify' => $contact['notify'], 'url' => $contact['url'],
                                'location' => $contact['location'], 'about' => $contact['about'],
                                'generation' => $contact['generation'], 'updated' => $contact['updated'],
-                               'server_url' => $contact['server_url'], 'connect' => $contact['connect']
+                               'server_url' => $contact['server_url'], 'connect' => $contact['connect'],
+                               'failed' => $contact['failed'], 'gsid' => $contact['gsid']
                        ];
 
                        DBA::update('gcontact', $updated, $condition, $fields);
@@ -818,19 +832,19 @@ class GContact
                        return false;
                }
 
-               $curlResult = Network::curl($gserver['noscrape'] . '/' . $data['nick']);
+               $curlResult = DI::httpRequest()->get($gserver['noscrape'] . '/' . $data['nick']);
 
                if ($curlResult->isSuccess() && !empty($curlResult->getBody())) {
                        $noscrape = json_decode($curlResult->getBody(), true);
                        if (!empty($noscrape) && !empty($noscrape['updated'])) {
                                $noscrape['updated'] = DateTimeFormat::utc($noscrape['updated'], DateTimeFormat::MYSQL);
-                               $fields = ['last_contact' => DateTimeFormat::utcNow(), 'updated' => $noscrape['updated']];
+                               $fields = ['failed' => false, 'last_contact' => DateTimeFormat::utcNow(), 'updated' => $noscrape['updated']];
                                DBA::update('gcontact', $fields, ['nurl' => Strings::normaliseLink($data['url'])]);
                                return true;
                        }
                } elseif ($curlResult->isTimeout()) {
                        // On a timeout return the existing value, but mark the contact as failure
-                       $fields = ['last_failure' => DateTimeFormat::utcNow()];
+                       $fields = ['failed' => true, 'last_failure' => DateTimeFormat::utcNow()];
                        DBA::update('gcontact', $fields, ['nurl' => Strings::normaliseLink($data['url'])]);
                        return true;
                }
@@ -855,11 +869,11 @@ class GContact
                        $items = $outbox['orderedItems'];
                } elseif (!empty($outbox['first']['orderedItems'])) {
                        $items = $outbox['first']['orderedItems'];
-               } elseif (!empty($outbox['first']['href'])) {
+               } elseif (!empty($outbox['first']['href']) && ($outbox['first']['href'] != $feed)) {
                        self::updateFromOutbox($outbox['first']['href'], $data);
                        return;
                } elseif (!empty($outbox['first'])) {
-                       if (is_string($outbox['first'])) {
+                       if (is_string($outbox['first']) && ($outbox['first'] != $feed)) {
                                self::updateFromOutbox($outbox['first'], $data);
                        } else {
                                Logger::warning('Unexpected data', ['outbox' => $outbox]);
@@ -888,7 +902,7 @@ class GContact
                        return;
                }
 
-               $fields = ['last_contact' => DateTimeFormat::utcNow(), 'updated' => $last_updated];
+               $fields = ['failed' => false, 'last_contact' => DateTimeFormat::utcNow(), 'updated' => $last_updated];
                DBA::update('gcontact', $fields, ['nurl' => Strings::normaliseLink($data['url'])]);
        }
 
@@ -900,10 +914,10 @@ class GContact
        private static function updateFromFeed(array $data)
        {
                // Search for the newest entry in the feed
-               $curlResult = Network::curl($data['poll']);
+               $curlResult = DI::httpRequest()->get($data['poll']);
                if (!$curlResult->isSuccess()) {
-                       $fields = ['last_failure' => DateTimeFormat::utcNow()];
-                       DBA::update('gcontact', $fields, ['nurl' => Strings::normaliseLink($profile)]);
+                       $fields = ['failed' => true, 'last_failure' => DateTimeFormat::utcNow()];
+                       DBA::update('gcontact', $fields, ['nurl' => Strings::normaliseLink($data['url'])]);
 
                        Logger::info("Profile wasn't reachable (no feed)", ['url' => $data['url']]);
                        return;
@@ -943,7 +957,7 @@ class GContact
                        return;
                }
 
-               $fields = ['last_contact' => DateTimeFormat::utcNow(), 'updated' => $last_updated];
+               $fields = ['failed' => false, 'last_contact' => DateTimeFormat::utcNow(), 'updated' => $last_updated];
                DBA::update('gcontact', $fields, ['nurl' => Strings::normaliseLink($data['url'])]);
        }
        /**
@@ -982,20 +996,20 @@ class GContact
         */
        private static function updateFromPublicContact($condition)
        {
-               $fields = ['name', 'nick', 'url', 'nurl', 'location', 'about', 'keywords', 'gender',
+               $fields = ['name', 'nick', 'url', 'nurl', 'location', 'about', 'keywords',
                        'bd', 'contact-type', 'network', 'addr', 'notify', 'alias', 'archive', 'term-date',
                        'created', 'updated', 'avatar', 'success_update', 'failure_update', 'forum', 'prv',
-                       'baseurl', 'sensitive', 'unsearchable'];
+                       'baseurl', 'gsid', 'sensitive', 'unsearchable', 'failed'];
 
                $contact = DBA::selectFirst('contact', $fields, array_merge($condition, ['uid' => 0, 'network' => Protocol::FEDERATED]));
                if (!DBA::isResult($contact)) {
                        return 0;
                }
 
-               $fields = ['name', 'nick', 'url', 'nurl', 'location', 'about', 'keywords', 'gender', 'generation',
+               $fields = ['name', 'nick', 'url', 'nurl', 'location', 'about', 'keywords', 'generation',
                        'birthday', 'contact-type', 'network', 'addr', 'notify', 'alias', 'archived', 'archive_date',
                        'created', 'updated', 'photo', 'last_contact', 'last_failure', 'community', 'connect',
-                       'server_url', 'nsfw', 'hide', 'id'];
+                       'server_url', 'gsid', 'nsfw', 'hide', 'id', 'failed'];
 
                $old_gcontact = DBA::selectFirst('gcontact', $fields, ['nurl' => $contact['nurl']]);
                $do_insert = !DBA::isResult($old_gcontact);
@@ -1006,8 +1020,8 @@ class GContact
                $gcontact = [];
 
                // These fields are identical in both contact and gcontact
-               $fields = ['name', 'nick', 'url', 'nurl', 'location', 'about', 'keywords', 'gender',
-                       'contact-type', 'network', 'addr', 'notify', 'alias', 'created', 'updated'];
+               $fields = ['name', 'nick', 'url', 'nurl', 'location', 'about', 'keywords', 'gsid',
+                       'contact-type', 'network', 'addr', 'notify', 'alias', 'created', 'updated', 'failed'];
 
                foreach ($fields as $field) {
                        $gcontact[$field] = $contact[$field];
@@ -1073,13 +1087,14 @@ class GContact
                $data = Probe::uri($url, $force);
 
                if (in_array($data['network'], [Protocol::PHANTOM])) {
-                       $fields = ['last_failure' => DateTimeFormat::utcNow()];
+                       $fields = ['failed' => true, 'last_failure' => DateTimeFormat::utcNow()];
                        DBA::update('gcontact', $fields, ['nurl' => Strings::normaliseLink($url)]);
                        Logger::info('Invalid network for contact', ['url' => $data['url'], 'callstack' => System::callstack()]);
                        return false;
                }
 
                $data['server_url'] = $data['baseurl'];
+               $data['failed'] = false;
 
                self::update($data);
 
@@ -1118,10 +1133,10 @@ class GContact
                );
 
                $gcontact = ['name' => $userdata['name'], 'location' => $location, 'about' => $userdata['about'],
-                               'gender' => $userdata['gender'], 'keywords' => $userdata['pub_keywords'],
+                               'keywords' => $userdata['pub_keywords'],
                                'birthday' => $userdata['dob'], 'photo' => $userdata['photo'],
                                "notify" => $userdata['notify'], 'url' => $userdata['url'],
-                               "hide" => ($userdata['hidewall'] || !$userdata['net-publish']),
+                               "hide" => !$userdata['net-publish'],
                                'nick' => $userdata['nickname'], 'addr' => $userdata['addr'],
                                "connect" => $userdata['addr'], "server_url" => DI::baseUrl(),
                                "generation" => 1, 'network' => Protocol::DFRN];
@@ -1177,7 +1192,7 @@ class GContact
 
                $url = $server . '/main/statistics';
 
-               $curlResult = Network::curl($url);
+               $curlResult = DI::httpRequest()->get($url);
                if (!$curlResult->isSuccess()) {
                        return false;
                }
@@ -1235,13 +1250,13 @@ class GContact
         */
        public static function discoverGsUsers()
        {
-               $requery_days = intval(Config::get('system', 'poco_requery_days'));
+               $requery_days = intval(DI::config()->get('system', 'poco_requery_days'));
 
                $last_update = date("c", time() - (60 * 60 * 24 * $requery_days));
 
                $r = DBA::select('gserver', ['nurl', 'url'], [
                        '`network` = ?
-                       AND `last_contact` >= `last_failure`
+                       AND NOT `failed`
                        AND `last_poco_query` < ?',
                        Protocol::OSTATUS,
                        $last_update
@@ -1269,8 +1284,8 @@ class GContact
        public static function getRandomUrl()
        {
                $r = DBA::selectFirst('gcontact', ['url'], [
-                       '`network` = ? 
-                       AND `last_contact` >= `last_failure`  
+                       '`network` = ?
+                       AND NOT `failed`
                        AND `updated` > ?',
                        Protocol::DFRN,
                        DateTimeFormat::utc('now - 1 month'),