X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FModel%2FContact.php;h=7c8dec3895b10a609924a38b0b07c1c21922df06;hb=fc0312451d3b8f8d10fc01701216fdd3a5139102;hp=c46b15b943af7ee9f7104ce2804519c7f573fba0;hpb=18745b1723b3f8580704914e8f9df8441c859e70;p=friendica.git diff --git a/src/Model/Contact.php b/src/Model/Contact.php index c46b15b943..7c8dec3895 100644 --- a/src/Model/Contact.php +++ b/src/Model/Contact.php @@ -190,6 +190,75 @@ class Contact return DBA::selectFirst('contact', $fields, ['id' => $id]); } + /** + * Fetches a contact by a given url + * + * @param string $url profile url + * @param integer $uid User ID of the contact + * @param array $fields Field list + * @param boolean $update true = always update, false = never update, null = update when not found or outdated + * @return array contact array + */ + public static function getByURL(string $url, $update = null, array $fields = [], int $uid = 0) + { + if ($update || is_null($update)) { + $cid = self::getIdForURL($url, $uid, !($update ?? false)); + if (empty($cid)) { + return []; + } + return self::getById($cid, $fields); + } + + // We first try the nurl (http://server.tld/nick), most common case + $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', $fields, ['addr' => str_replace('acct:', '', $url), 'uid' => $uid, 'deleted' => false], $options); + } + + // Then the alias (which could be anything) + if (!DBA::isResult($contact)) { + // 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', $fields, $condition, $options); + } + return $contact; + } + + /** + * Fetches a contact for a given user by a given url. + * In difference to "getByURL" the function will fetch a public contact when no user contact had been found. + * + * @param string $url profile url + * @param integer $uid User ID of the contact + * @param array $fields Field list + * @param boolean $update true = always update, false = never update, null = update when not found or outdated + * @return array contact array + */ + public static function getByURLForUser(string $url, int $uid = 0, array $fields = [], $update = null) + { + if ($uid != 0) { + $contact = self::getByURL($url, $update, $fields, $uid); + if (!empty($contact)) { + if (!empty($contact['id'])) { + $contact['cid'] = $contact['id']; + $contact['zid'] = 0; + } + return $contact; + } + } + + $contact = self::getByURL($url, $update, $fields); + if (!empty($contact['id'])) { + $contact['cid'] = 0; + $contact['zid'] = $contact['id']; + } + return $contact; + } + /** * Tests if the given contact is a follower * @@ -843,6 +912,7 @@ class Contact // create an unfollow slap $item = []; $item['verb'] = Activity::O_UNFOLLOW; + $item['gravity'] = GRAVITY_ACTIVITY; $item['follow'] = $contact["url"]; $item['body'] = ''; $item['title'] = ''; @@ -887,10 +957,10 @@ class Contact return; } } elseif (!isset($contact['url'])) { - Logger::log('Empty contact: ' . json_encode($contact) . ' - ' . System::callstack(20), Logger::DEBUG); + Logger::info('Empty contact', ['contact' => $contact, 'callstack' => System::callstack(20)]); } - Logger::log('Contact '.$contact['id'].' is marked for archival', Logger::DEBUG); + Logger::info('Contact is marked for archival', ['id' => $contact['id']]); // Contact already archived or "self" contact? => nothing to do if ($contact['archive'] || $contact['self']) { @@ -949,7 +1019,7 @@ class Contact return; } - Logger::log('Contact '.$contact['id'].' is marked as vital again', Logger::DEBUG); + Logger::info('Contact is marked as vital again', ['id' => $contact['id']]); if (!isset($contact['url']) && !empty($contact['id'])) { $fields = ['id', 'url', 'batch']; @@ -966,216 +1036,6 @@ class Contact GContact::updateFromPublicContactURL($contact['url']); } - /** - * Get contact data for a given profile link - * - * The function looks at several places (contact table and gcontact table) for the contact - * It caches its result for the same script execution to prevent duplicate calls - * - * @param string $url The profile link - * @param int $uid User id - * @param array $default If not data was found take this data as default value - * - * @return array Contact data - * @throws HTTPException\InternalServerErrorException - */ - public static function getDetailsByURL($url, $uid = -1, array $default = []) - { - static $cache = []; - - if ($url == '') { - return $default; - } - - if ($uid == -1) { - $uid = local_user(); - } - - if (isset($cache[$url][$uid])) { - return $cache[$url][$uid]; - } - - $ssl_url = str_replace('http://', 'https://', $url); - - $nurl = Strings::normaliseLink($url); - - // Fetch contact data from the contact table for the given user - $s = DBA::p("SELECT `id`, `id` AS `cid`, 0 AS `gid`, 0 AS `zid`, `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, `xmpp`, - `keywords`, `photo`, `thumb`, `micro`, `forum`, `prv`, (`forum` | `prv`) AS `community`, `contact-type`, `bd` AS `birthday`, `self`, `rel`, `pending` - FROM `contact` WHERE `nurl` = ? AND `uid` = ?", $nurl, $uid); - $r = DBA::toArray($s); - - // Fetch contact data from the contact table for the given user, checking with the alias - if (!DBA::isResult($r)) { - $s = DBA::p("SELECT `id`, `id` AS `cid`, 0 AS `gid`, 0 AS `zid`, `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, `xmpp`, - `keywords`, `photo`, `thumb`, `micro`, `forum`, `prv`, (`forum` | `prv`) AS `community`, `contact-type`, `bd` AS `birthday`, `self`, `rel`, `pending` - FROM `contact` WHERE `alias` IN (?, ?, ?) AND `uid` = ?", $nurl, $url, $ssl_url, $uid); - $r = DBA::toArray($s); - } - - // Fetch the data from the contact table with "uid=0" (which is filled automatically) - if (!DBA::isResult($r)) { - $s = DBA::p("SELECT `id`, 0 AS `cid`, `id` AS `zid`, 0 AS `gid`, `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, `xmpp`, - `keywords`, `photo`, `thumb`, `micro`, `forum`, `prv`, (`forum` | `prv`) AS `community`, `contact-type`, `bd` AS `birthday`, 0 AS `self`, `rel`, `pending` - FROM `contact` WHERE `nurl` = ? AND `uid` = 0", $nurl); - $r = DBA::toArray($s); - } - - // Fetch the data from the contact table with "uid=0" (which is filled automatically) - checked with the alias - if (!DBA::isResult($r)) { - $s = DBA::p("SELECT `id`, 0 AS `cid`, `id` AS `zid`, 0 AS `gid`, `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, `xmpp`, - `keywords`, `photo`, `thumb`, `micro`, `forum`, `prv`, (`forum` | `prv`) AS `community`, `contact-type`, `bd` AS `birthday`, 0 AS `self`, `rel`, `pending` - FROM `contact` WHERE `alias` IN (?, ?, ?) AND `uid` = 0", $nurl, $url, $ssl_url); - $r = DBA::toArray($s); - } - - // Fetch the data from the gcontact table - if (!DBA::isResult($r)) { - $s = DBA::p("SELECT 0 AS `id`, 0 AS `cid`, `id` AS `gid`, 0 AS `zid`, 0 AS `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, '' AS `xmpp`, - `keywords`, `photo`, `photo` AS `thumb`, `photo` AS `micro`, 0 AS `forum`, 0 AS `prv`, `community`, `contact-type`, `birthday`, 0 AS `self`, 2 AS `rel`, 0 AS `pending` - FROM `gcontact` WHERE `nurl` = ?", $nurl); - $r = DBA::toArray($s); - } - - if (DBA::isResult($r)) { - $authoritativeResult = true; - // If there is more than one entry we filter out the connector networks - if (count($r) > 1) { - foreach ($r as $id => $result) { - if (!in_array($result["network"], Protocol::NATIVE_SUPPORT)) { - unset($r[$id]); - } - } - } - - $profile = array_shift($r); - - // "bd" always contains the upcoming birthday of a contact. - // "birthday" might contain the birthday including the year of birth. - if ($profile["birthday"] > DBA::NULL_DATE) { - $bd_timestamp = strtotime($profile["birthday"]); - $month = date("m", $bd_timestamp); - $day = date("d", $bd_timestamp); - - $current_timestamp = time(); - $current_year = date("Y", $current_timestamp); - $current_month = date("m", $current_timestamp); - $current_day = date("d", $current_timestamp); - - $profile["bd"] = $current_year . "-" . $month . "-" . $day; - $current = $current_year . "-" . $current_month . "-" . $current_day; - - if ($profile["bd"] < $current) { - $profile["bd"] = ( ++$current_year) . "-" . $month . "-" . $day; - } - } else { - $profile["bd"] = DBA::NULL_DATE; - } - } else { - $authoritativeResult = false; - $profile = $default; - } - - if (empty($profile["photo"]) && isset($default["photo"])) { - $profile["photo"] = $default["photo"]; - } - - if (empty($profile["name"]) && isset($default["name"])) { - $profile["name"] = $default["name"]; - } - - if (empty($profile["network"]) && isset($default["network"])) { - $profile["network"] = $default["network"]; - } - - if (empty($profile["thumb"]) && isset($profile["photo"])) { - $profile["thumb"] = $profile["photo"]; - } - - if (empty($profile["micro"]) && isset($profile["thumb"])) { - $profile["micro"] = $profile["thumb"]; - } - - if ((empty($profile["addr"]) || empty($profile["name"])) && !empty($profile["gid"]) - && in_array($profile["network"], Protocol::FEDERATED) - ) { - Worker::add(PRIORITY_LOW, "UpdateGContact", $url); - } - - // Show contact details of Diaspora contacts only if connected - if (empty($profile["cid"]) && ($profile["network"] ?? "") == Protocol::DIASPORA) { - $profile["location"] = ""; - $profile["about"] = ""; - $profile["birthday"] = DBA::NULL_DATE; - } - - // Only cache the result if it came from the DB since this method is used in widely different contexts - // @see display_fetch_author for an example of $default parameter diverging from the DB result - if ($authoritativeResult) { - $cache[$url][$uid] = $profile; - } - - return $profile; - } - - /** - * Get contact data for a given address - * - * The function looks at several places (contact table and gcontact table) for the contact - * - * @param string $addr The profile link - * @param int $uid User id - * - * @return array Contact data - * @throws HTTPException\InternalServerErrorException - * @throws \ImagickException - */ - public static function getDetailsByAddr($addr, $uid = -1) - { - if ($addr == '') { - return []; - } - - if ($uid == -1) { - $uid = local_user(); - } - - // Fetch contact data from the contact table for the given user - $r = q("SELECT `id`, `id` AS `cid`, 0 AS `gid`, 0 AS `zid`, `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, `xmpp`, - `keywords`, `photo`, `thumb`, `micro`, `forum`, `prv`, (`forum` | `prv`) AS `community`, `contact-type`, `bd` AS `birthday`, `self`, `rel`, `pending`,`baseurl` - FROM `contact` WHERE `addr` = '%s' AND `uid` = %d AND NOT `deleted`", - DBA::escape($addr), - intval($uid) - ); - // Fetch the data from the contact table with "uid=0" (which is filled automatically) - if (!DBA::isResult($r)) { - $r = q("SELECT `id`, 0 AS `cid`, `id` AS `zid`, 0 AS `gid`, `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, `xmpp`, - `keywords`, `photo`, `thumb`, `micro`, `forum`, `prv`, (`forum` | `prv`) AS `community`, `contact-type`, `bd` AS `birthday`, 0 AS `self`, `rel`, `pending`, `baseurl` - FROM `contact` WHERE `addr` = '%s' AND `uid` = 0 AND NOT `deleted`", - DBA::escape($addr) - ); - } - - // Fetch the data from the gcontact table - if (!DBA::isResult($r)) { - $r = q("SELECT 0 AS `id`, 0 AS `cid`, `id` AS `gid`, 0 AS `zid`, 0 AS `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, '' AS `xmpp`, - `keywords`, `photo`, `photo` AS `thumb`, `photo` AS `micro`, `community` AS `forum`, 0 AS `prv`, `community`, `contact-type`, `birthday`, 0 AS `self`, 2 AS `rel`, 0 AS `pending`, `server_url` AS `baseurl` - FROM `gcontact` WHERE `addr` = '%s'", - DBA::escape($addr) - ); - } - - if (!DBA::isResult($r)) { - $data = Probe::uri($addr); - - $profile = self::getDetailsByURL($data['url'], $uid, $data); - } else { - $profile = $r[0]; - } - - return $profile; - } - /** * Returns the data array for the photo menu of a given contact * @@ -1450,7 +1310,7 @@ class Contact */ public static function getIdForURL($url, $uid = 0, $no_update = false, $default = [], $in_loop = false) { - Logger::log("Get contact data for url " . $url . " and user " . $uid . " - " . System::callstack(), Logger::DEBUG); + Logger::info('Get contact data', ['url' => $url, 'user' => $uid]); $contact_id = 0; @@ -1458,26 +1318,9 @@ class Contact return 0; } - /// @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 - $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', $fields, ['addr' => str_replace('acct:', '', $url), 'uid' => $uid, 'deleted' => false], $options); - } - - // Then the alias (which could be anything) - if (!DBA::isResult($contact)) { - // 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', $fields, $condition, $options); - } + $contact = self::getByURL($url, false, ['id', 'avatar', 'updated', 'network'], $uid); - if (DBA::isResult($contact)) { + if (!empty($contact)) { $contact_id = $contact["id"]; $update_contact = false; @@ -1550,7 +1393,7 @@ class Contact $data['gsid'] = GServer::getID($data['baseurl']); } - if (!$contact_id && !empty($data['alias']) && ($data['alias'] != $url) && !$in_loop) { + if (!$contact_id && !empty($data['alias']) && ($data['alias'] != $data['url']) && !$in_loop) { $contact_id = self::getIdForURL($data["alias"], $uid, true, $default, true); } @@ -2331,11 +2174,11 @@ class Contact $condition = ['uid' => $user['uid'], 'poll' => [$ret['poll'], Strings::normaliseLink($ret['poll'])], 'network' => $ret['network'], 'pending' => false]; $contact = DBA::selectFirst('contact', ['id', 'rel'], $condition); if (!DBA::isResult($contact)) { - $condition = ['uid' => $user['uid'], 'nurl' => Strings::normaliseLink($url), 'network' => $ret['network'], 'pending' => false]; + $condition = ['uid' => $user['uid'], 'nurl' => Strings::normaliseLink($ret['url']), 'network' => $ret['network'], 'pending' => false]; $contact = DBA::selectFirst('contact', ['id', 'rel'], $condition); } - $protocol = self::getProtocol($url, $ret['network']); + $protocol = self::getProtocol($ret['url'], $ret['network']); if (($protocol === Protocol::DFRN) && !DBA::isResult($contact)) { if ($interactive) { @@ -2372,7 +2215,7 @@ class Contact if (empty($ret['url'])) { $result['message'] .= DI::l10n()->t('No browser URL could be matched to this address.') . EOL; } - if (strpos($url, '@') !== false) { + if (strpos($ret['url'], '@') !== false) { $result['message'] .= DI::l10n()->t('Unable to match @-style Identity Address with a known protocol or email contact.') . EOL; $result['message'] .= DI::l10n()->t('Use mailto: in front of address to force email check.') . EOL; } @@ -2396,7 +2239,7 @@ class Contact $pending = false; if ($protocol == Protocol::ACTIVITYPUB) { - $apcontact = APContact::getByURL($url, false); + $apcontact = APContact::getByURL($ret['url'], false); if (isset($apcontact['manually-approve'])) { $pending = (bool)$apcontact['manually-approve']; } @@ -2470,6 +2313,7 @@ class Contact // create a follow slap $item = []; $item['verb'] = Activity::FOLLOW; + $item['gravity'] = GRAVITY_ACTIVITY; $item['follow'] = $contact["url"]; $item['body'] = ''; $item['title'] = '';