X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FModel%2FGContact.php;h=ec53133c941ba040461a4f35ed2154d1efd14efe;hb=6749b2c887552feef3a671c4063425b11a92014a;hp=6401c8baab141b49f3e08a62ad0a028a57d83ac2;hpb=af88c2daa34e39cb6430abf64d0648665bfeb9cd;p=friendica.git diff --git a/src/Model/GContact.php b/src/Model/GContact.php index 6401c8baab..ec53133c94 100644 --- a/src/Model/GContact.php +++ b/src/Model/GContact.php @@ -1,18 +1,34 @@ . + * */ + 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'),