From fd62629285f1aaa88682af448da26e5a05b60932 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 5 Aug 2020 06:50:51 +0000 Subject: [PATCH 1/9] Probe for the date of the last item --- src/Model/Contact.php | 187 ++---------------------------------------- src/Network/Probe.php | 158 +++++++++++++++++++++++++++++++++++ 2 files changed, 167 insertions(+), 178 deletions(-) diff --git a/src/Model/Contact.php b/src/Model/Contact.php index 08cde31eeb..39c955d74a 100644 --- a/src/Model/Contact.php +++ b/src/Model/Contact.php @@ -1235,6 +1235,9 @@ class Contact $data['gsid'] = GServer::getID($data['baseurl']); } + $data['last-item'] = Probe::getLastUpdate($data); + Logger::info('Fetched last item', ['url' => $data['url'], 'last-item' => $data['last-item']]); + if (!$contact_id && !empty($data['alias']) && ($data['alias'] != $data['url']) && !$in_loop) { $contact_id = self::getIdForURL($data["alias"], $uid, false, $default, true); } @@ -1264,6 +1267,7 @@ class Contact 'poco' => $data['poco'] ?? '', 'baseurl' => $data['baseurl'] ?? '', 'gsid' => $data['gsid'] ?? null, + 'last-item' => $data['last-item'], 'name-date' => DateTimeFormat::utcNow(), 'uri-date' => DateTimeFormat::utcNow(), 'avatar-date' => DateTimeFormat::utcNow(), @@ -1308,7 +1312,7 @@ class Contact self::updateFromProbe($contact_id, '', false); } } else { - $fields = ['url', 'nurl', 'addr', 'alias', 'name', 'nick', 'keywords', 'location', 'about', 'avatar-date', 'baseurl', 'gsid']; + $fields = ['url', 'nurl', 'addr', 'alias', 'name', 'nick', 'keywords', 'location', 'about', 'avatar-date', 'baseurl', 'gsid', 'last-item']; $contact = DBA::selectFirst('contact', $fields, ['id' => $contact_id]); // This condition should always be true @@ -1329,6 +1333,10 @@ class Contact $updated[$field] = ($data[$field] ?? '') ?: $contact[$field]; } + if ($contact['last-item'] < $data['last-item']) { + $updated['last-item'] = $data['last-item']; + } + if (($updated['addr'] != $contact['addr']) || (!empty($data['alias']) && ($data['alias'] != $contact['alias']))) { $updated['uri-date'] = DateTimeFormat::utcNow(); } @@ -2806,183 +2814,6 @@ class Contact return ['count' => $count, 'added' => $added, 'updated' => $updated]; } - /** - * Set the last date that the contact had posted something - * - * This functionality is currently unused - * - * @param string $data probing result - * @param bool $force force updating - */ - private static function setLastUpdate(array $data, bool $force = false) - { - $contact = self::getByURL($data['url'], false, []); - if (empty($contact)) { - return; - } - if (!$force && !GServer::updateNeeded($contact['created'], $contact['updated'], $contact['last_failure'], $contact['last_contact'])) { - Logger::info("Don't update profile", ['url' => $data['url'], 'updated' => $contact['updated']]); - return; - } - - if (self::updateFromNoScrape($data)) { - return; - } - - if (!empty($data['outbox'])) { - self::updateFromOutbox($data['outbox'], $data); - } elseif (!empty($data['poll']) && ($data['network'] == Protocol::ACTIVITYPUB)) { - self::updateFromOutbox($data['poll'], $data); - } elseif (!empty($data['poll'])) { - self::updateFromFeed($data); - } - } - - /** - * Update a global contact via the "noscrape" endpoint - * - * @param string $data Probing result - * - * @return bool 'true' if update was successful or the server was unreachable - */ - private static function updateFromNoScrape(array $data) - { - // Check the 'noscrape' endpoint when it is a Friendica server - $gserver = DBA::selectFirst('gserver', ['noscrape'], ["`nurl` = ? AND `noscrape` != ''", - Strings::normaliseLink($data['baseurl'])]); - if (!DBA::isResult($gserver)) { - return false; - } - - $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 = ['failed' => false, 'last_contact' => DateTimeFormat::utcNow(), 'updated' => $noscrape['updated']]; - DBA::update('contact', $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 = ['failed' => true, 'last_failure' => DateTimeFormat::utcNow()]; - DBA::update('contact', $fields, ['nurl' => Strings::normaliseLink($data['url'])]); - return true; - } - return false; - } - - /** - * Update a global contact via an ActivityPub Outbox - * - * @param string $feed - * @param array $data Probing result - * @throws \Friendica\Network\HTTPException\InternalServerErrorException - */ - private static function updateFromOutbox(string $feed, array $data) - { - $outbox = ActivityPub::fetchContent($feed); - if (empty($outbox)) { - return; - } - - if (!empty($outbox['orderedItems'])) { - $items = $outbox['orderedItems']; - } elseif (!empty($outbox['first']['orderedItems'])) { - $items = $outbox['first']['orderedItems']; - } 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']) && ($outbox['first'] != $feed)) { - self::updateFromOutbox($outbox['first'], $data); - } else { - Logger::warning('Unexpected data', ['outbox' => $outbox]); - } - return; - } else { - $items = []; - } - - $last_updated = ''; - foreach ($items as $activity) { - if (!empty($activity['published'])) { - $published = DateTimeFormat::utc($activity['published']); - } elseif (!empty($activity['object']['published'])) { - $published = DateTimeFormat::utc($activity['object']['published']); - } else { - continue; - } - - if ($last_updated < $published) { - $last_updated = $published; - } - } - - if (empty($last_updated)) { - return; - } - - $fields = ['failed' => false, 'last_contact' => DateTimeFormat::utcNow(), 'updated' => $last_updated]; - DBA::update('contact', $fields, ['nurl' => Strings::normaliseLink($data['url'])]); - } - - /** - * Update a global contact via an XML feed - * - * @param string $data Probing result - */ - private static function updateFromFeed(array $data) - { - // Search for the newest entry in the feed - $curlResult = DI::httpRequest()->get($data['poll']); - if (!$curlResult->isSuccess()) { - $fields = ['failed' => true, 'last_failure' => DateTimeFormat::utcNow()]; - DBA::update('contact', $fields, ['nurl' => Strings::normaliseLink($data['url'])]); - - Logger::info("Profile wasn't reachable (no feed)", ['url' => $data['url']]); - return; - } - - $doc = new DOMDocument(); - @$doc->loadXML($curlResult->getBody()); - - $xpath = new DOMXPath($doc); - $xpath->registerNamespace('atom', 'http://www.w3.org/2005/Atom'); - - $entries = $xpath->query('/atom:feed/atom:entry'); - - $last_updated = ''; - - foreach ($entries as $entry) { - $published_item = $xpath->query('atom:published/text()', $entry)->item(0); - $updated_item = $xpath->query('atom:updated/text()' , $entry)->item(0); - $published = !empty($published_item->nodeValue) ? DateTimeFormat::utc($published_item->nodeValue) : null; - $updated = !empty($updated_item->nodeValue) ? DateTimeFormat::utc($updated_item->nodeValue) : null; - - if (empty($published) || empty($updated)) { - Logger::notice('Invalid entry for XPath.', ['entry' => $entry, 'url' => $data['url']]); - continue; - } - - if ($last_updated < $published) { - $last_updated = $published; - } - - if ($last_updated < $updated) { - $last_updated = $updated; - } - } - - if (empty($last_updated)) { - return; - } - - $fields = ['failed' => false, 'last_contact' => DateTimeFormat::utcNow(), 'updated' => $last_updated]; - DBA::update('contact', $fields, ['nurl' => Strings::normaliseLink($data['url'])]); - } - /** * Returns a random, global contact of the current node * diff --git a/src/Network/Probe.php b/src/Network/Probe.php index 3c43fb28ea..53418ecb61 100644 --- a/src/Network/Probe.php +++ b/src/Network/Probe.php @@ -38,6 +38,7 @@ use Friendica\Protocol\ActivityPub; use Friendica\Protocol\Email; use Friendica\Protocol\Feed; use Friendica\Util\Crypto; +use Friendica\Util\DateTimeFormat; use Friendica\Util\Network; use Friendica\Util\Strings; use Friendica\Util\XML; @@ -2009,4 +2010,161 @@ class Probe return $fixed; } + + /** + * Fetch the last date that the contact had posted something (publically) + * + * @param string $data probing result + * @return string last activity + */ + public static function getLastUpdate(array $data) + { + if ($lastUpdate = self::updateFromNoScrape($data)) { + return $lastUpdate; + } + + if (!empty($data['outbox'])) { + return self::updateFromOutbox($data['outbox'], $data); + } elseif (!empty($data['poll']) && ($data['network'] == Protocol::ACTIVITYPUB)) { + return self::updateFromOutbox($data['poll'], $data); + } elseif (!empty($data['poll'])) { + return self::updateFromFeed($data); + } + + return ''; + } + + /** + * Fetch the last activity date from the "noscrape" endpoint + * + * @param array $data Probing result + * @return string last activity + * + * @return bool 'true' if update was successful or the server was unreachable + */ + private static function updateFromNoScrape(array $data) + { + // Check the 'noscrape' endpoint when it is a Friendica server + $gserver = DBA::selectFirst('gserver', ['noscrape'], ["`nurl` = ? AND `noscrape` != ''", + Strings::normaliseLink($data['baseurl'])]); + if (!DBA::isResult($gserver)) { + return ''; + } + + $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'])) { + return DateTimeFormat::utc($noscrape['updated'], DateTimeFormat::MYSQL); + } + } + + return ''; + } + + /** + * Fetch the last activity date from an ActivityPub Outbox + * + * @param string $feed + * @param array $data Probing result + * @return string last activity + * @throws \Friendica\Network\HTTPException\InternalServerErrorException + */ + private static function updateFromOutbox(string $feed, array $data) + { + $outbox = ActivityPub::fetchContent($feed); + if (empty($outbox)) { + return ''; + } + + if (!empty($outbox['orderedItems'])) { + $items = $outbox['orderedItems']; + } elseif (!empty($outbox['first']['orderedItems'])) { + $items = $outbox['first']['orderedItems']; + } elseif (!empty($outbox['first']['href']) && ($outbox['first']['href'] != $feed)) { + return self::updateFromOutbox($outbox['first']['href'], $data); + } elseif (!empty($outbox['first'])) { + if (is_string($outbox['first']) && ($outbox['first'] != $feed)) { + return self::updateFromOutbox($outbox['first'], $data); + } else { + Logger::warning('Unexpected data', ['outbox' => $outbox]); + } + return ''; + } else { + $items = []; + } + + $last_updated = ''; + foreach ($items as $activity) { + if (!empty($activity['published'])) { + $published = DateTimeFormat::utc($activity['published']); + } elseif (!empty($activity['object']['published'])) { + $published = DateTimeFormat::utc($activity['object']['published']); + } else { + continue; + } + + if ($last_updated < $published) { + $last_updated = $published; + } + } + + if (!empty($last_updated)) { + return $last_updated; + } + + return ''; + } + + /** + * Fetch the last activity date from an XML feed + * + * @param array $data Probing result + * @return string last activity + */ + private static function updateFromFeed(array $data) + { + // Search for the newest entry in the feed + $curlResult = DI::httpRequest()->get($data['poll']); + if (!$curlResult->isSuccess()) { + return ''; + } + + $doc = new DOMDocument(); + @$doc->loadXML($curlResult->getBody()); + + $xpath = new DOMXPath($doc); + $xpath->registerNamespace('atom', 'http://www.w3.org/2005/Atom'); + + $entries = $xpath->query('/atom:feed/atom:entry'); + + $last_updated = ''; + + foreach ($entries as $entry) { + $published_item = $xpath->query('atom:published/text()', $entry)->item(0); + $updated_item = $xpath->query('atom:updated/text()' , $entry)->item(0); + $published = !empty($published_item->nodeValue) ? DateTimeFormat::utc($published_item->nodeValue) : null; + $updated = !empty($updated_item->nodeValue) ? DateTimeFormat::utc($updated_item->nodeValue) : null; + + if (empty($published) || empty($updated)) { + Logger::notice('Invalid entry for XPath.', ['entry' => $entry, 'url' => $data['url']]); + continue; + } + + if ($last_updated < $published) { + $last_updated = $published; + } + + if ($last_updated < $updated) { + $last_updated = $updated; + } + } + + if (!empty($last_updated)) { + return $last_updated; + } + + return ''; + } } From cd99b9706b75c8719e3df29f2dbbad4689ee2ed9 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 5 Aug 2020 07:51:15 +0000 Subject: [PATCH 2/9] Check for empty baseurl --- src/Network/Probe.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Network/Probe.php b/src/Network/Probe.php index 53418ecb61..c4f4e57f29 100644 --- a/src/Network/Probe.php +++ b/src/Network/Probe.php @@ -2044,9 +2044,13 @@ class Probe */ private static function updateFromNoScrape(array $data) { + if (empty($data['baseurl'])) { + return ''; + } + // Check the 'noscrape' endpoint when it is a Friendica server $gserver = DBA::selectFirst('gserver', ['noscrape'], ["`nurl` = ? AND `noscrape` != ''", - Strings::normaliseLink($data['baseurl'])]); + Strings::normaliseLink($data['baseurl'])]); if (!DBA::isResult($gserver)) { return ''; } From 3a4be3d5f468d5bedb56199becdaba87fd543f94 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 5 Aug 2020 08:06:47 +0000 Subject: [PATCH 3/9] Fill "last-item" with an empty date when bo date had been provided --- src/Model/Contact.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Model/Contact.php b/src/Model/Contact.php index 39c955d74a..934c628d8e 100644 --- a/src/Model/Contact.php +++ b/src/Model/Contact.php @@ -1218,11 +1218,11 @@ class Contact } // Take the default values when probing failed - if (!empty($default) && !in_array($data["network"], array_merge(Protocol::NATIVE_SUPPORT, [Protocol::PUMPIO]))) { + if (!empty($default) && (empty($data['network']) || !in_array($data["network"], array_merge(Protocol::NATIVE_SUPPORT, [Protocol::PUMPIO])))) { $data = array_merge($data, $default); } - if (empty($data) || ($data['network'] == Protocol::PHANTOM)) { + if (empty($data['network']) || ($data['network'] == Protocol::PHANTOM)) { Logger::info('No valid network found', ['url' => $url, 'data' => $data, 'callstack' => System::callstack(20)]); return 0; } @@ -1267,7 +1267,7 @@ class Contact 'poco' => $data['poco'] ?? '', 'baseurl' => $data['baseurl'] ?? '', 'gsid' => $data['gsid'] ?? null, - 'last-item' => $data['last-item'], + 'last-item' => $data['last-item'] ?: DBA::NULL_DATETIME, 'name-date' => DateTimeFormat::utcNow(), 'uri-date' => DateTimeFormat::utcNow(), 'avatar-date' => DateTimeFormat::utcNow(), From 2280f5294522de9283b40235a407389a8593dc56 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 5 Aug 2020 08:24:01 +0000 Subject: [PATCH 4/9] Only query the last item on public contacts --- src/Model/Contact.php | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/Model/Contact.php b/src/Model/Contact.php index 934c628d8e..278632072d 100644 --- a/src/Model/Contact.php +++ b/src/Model/Contact.php @@ -1235,8 +1235,10 @@ class Contact $data['gsid'] = GServer::getID($data['baseurl']); } - $data['last-item'] = Probe::getLastUpdate($data); - Logger::info('Fetched last item', ['url' => $data['url'], 'last-item' => $data['last-item']]); + if ($uid == 0) { + $data['last-item'] = Probe::getLastUpdate($data); + Logger::info('Fetched last item', ['url' => $data['url'], 'last-item' => $data['last-item']]); + } if (!$contact_id && !empty($data['alias']) && ($data['alias'] != $data['url']) && !$in_loop) { $contact_id = self::getIdForURL($data["alias"], $uid, false, $default, true); @@ -1267,7 +1269,6 @@ class Contact 'poco' => $data['poco'] ?? '', 'baseurl' => $data['baseurl'] ?? '', 'gsid' => $data['gsid'] ?? null, - 'last-item' => $data['last-item'] ?: DBA::NULL_DATETIME, 'name-date' => DateTimeFormat::utcNow(), 'uri-date' => DateTimeFormat::utcNow(), 'avatar-date' => DateTimeFormat::utcNow(), @@ -1276,6 +1277,10 @@ class Contact 'readonly' => 0, 'pending' => 0]; + if (!empty($data['last-item'])) { + $fields['last-item'] = $data['last-item']; + } + $condition = ['nurl' => Strings::normaliseLink($data["url"]), 'uid' => $uid, 'deleted' => false]; // Before inserting we do check if the entry does exist now. @@ -1333,7 +1338,7 @@ class Contact $updated[$field] = ($data[$field] ?? '') ?: $contact[$field]; } - if ($contact['last-item'] < $data['last-item']) { + if (!empty($data['last-item']) && ($contact['last-item'] < $data['last-item'])) { $updated['last-item'] = $data['last-item']; } From 1f164f66f401ce8f026c3626a6ec1fa441448cb8 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 5 Aug 2020 12:35:38 +0000 Subject: [PATCH 5/9] Simplify contact search --- src/Protocol/Diaspora.php | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/src/Protocol/Diaspora.php b/src/Protocol/Diaspora.php index feb1111443..5e4ed9ee17 100644 --- a/src/Protocol/Diaspora.php +++ b/src/Protocol/Diaspora.php @@ -1106,20 +1106,7 @@ class Diaspora */ private static function contactByHandle($uid, $handle) { - $cid = Contact::getIdForURL($handle, $uid); - if (!$cid) { - Logger::log("Haven't found a contact for user " . $uid . " and handle " . $handle, Logger::DEBUG); - return false; - } - - $contact = DBA::selectFirst('contact', [], ['id' => $cid]); - if (!DBA::isResult($contact)) { - // This here shouldn't happen at all - Logger::log("Haven't found a contact for user " . $uid . " and handle " . $handle, Logger::DEBUG); - return false; - } - - return $contact; + return Contact::getByURL($handle, null, [], $uid); } /** From 187dbc09acb26b4fc0119de5feb63702f7c0bfc4 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 5 Aug 2020 12:36:04 +0000 Subject: [PATCH 6/9] Avoid double probing --- src/Model/Contact.php | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/Model/Contact.php b/src/Model/Contact.php index 278632072d..18f0b020e2 100644 --- a/src/Model/Contact.php +++ b/src/Model/Contact.php @@ -1158,13 +1158,12 @@ class Contact * @param integer $uid The user id for the contact (0 = public contact) * @param boolean $update true = always update, false = never update, null = update when not found or outdated * @param array $default Default value for creating the contact when every else fails - * @param boolean $in_loop Internally used variable to prevent an endless loop * * @return integer Contact ID * @throws HTTPException\InternalServerErrorException * @throws \ImagickException */ - public static function getIdForURL($url, $uid = 0, $update = null, $default = [], $in_loop = false) + public static function getIdForURL($url, $uid = 0, $update = null, $default = []) { Logger::info('Get contact data', ['url' => $url, 'user' => $uid]); @@ -1235,13 +1234,16 @@ class Contact $data['gsid'] = GServer::getID($data['baseurl']); } - if ($uid == 0) { - $data['last-item'] = Probe::getLastUpdate($data); - Logger::info('Fetched last item', ['url' => $data['url'], 'last-item' => $data['last-item']]); + if (!$contact_id && !empty($data['alias']) && ($data['alias'] != $data['url'])) { + $contact = self::getByURL($data['alias'], false, ['id']); + if (!empty($contact['id'])) { + $contact_id = $contact['id']; + } } - if (!$contact_id && !empty($data['alias']) && ($data['alias'] != $data['url']) && !$in_loop) { - $contact_id = self::getIdForURL($data["alias"], $uid, false, $default, true); + if ($uid == 0) { + $data['last-item'] = Probe::getLastUpdate($data); + Logger::info('Fetched last item', ['url' => $url, 'probed_url' => $data['url'], 'last-item' => $data['last-item'], 'callstack' => System::callstack(20)]); } if (!$contact_id) { From 4e5a3ab0f11591d04a1afee406b09186818e68b5 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 5 Aug 2020 12:53:02 +0000 Subject: [PATCH 7/9] Added checked for URL change --- src/Model/Contact.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Model/Contact.php b/src/Model/Contact.php index 18f0b020e2..b565e7e50b 100644 --- a/src/Model/Contact.php +++ b/src/Model/Contact.php @@ -1238,6 +1238,16 @@ class Contact $contact = self::getByURL($data['alias'], false, ['id']); if (!empty($contact['id'])) { $contact_id = $contact['id']; + Logger::info('Fetched id by alias', ['cid' => $contact_id, 'url' => $url, 'probed_url' => $data['url'], 'alias' => $data['alias']]); + } + } + + // Possibly there is a contact entry with the probed URL + if (!$contact_id && ($url != $data['url']) && ($url != $data['alias'])) { + $contact = self::getByURL($data['url'], false, ['id']); + if (!empty($contact['id'])) { + $contact_id = $contact['id']; + Logger::info('Fetched id by url', ['cid' => $contact_id, 'url' => $url, 'probed_url' => $data['url'], 'alias' => $data['alias']]); } } From 603b1f965d181ad20ecfcd7ca2993baa7f103778 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 5 Aug 2020 12:53:25 +0000 Subject: [PATCH 8/9] Fix wrong value for parameter --- src/Protocol/OStatus.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Protocol/OStatus.php b/src/Protocol/OStatus.php index d9e18fa613..74a055265d 100644 --- a/src/Protocol/OStatus.php +++ b/src/Protocol/OStatus.php @@ -2017,7 +2017,7 @@ class OStatus $mentioned = $newmentions; foreach ($mentioned as $mention) { - $contact = Contact::getByURL($mention, ['contact-type']); + $contact = Contact::getByURL($mention, false, ['contact-type']); if (!empty($contact) && ($contact['contact-type'] == Contact::TYPE_COMMUNITY)) { XML::addElement($doc, $entry, "link", "", [ From d56ac8d58f6e9ec0dd104ac19e74aeb0af86351a Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 5 Aug 2020 12:57:02 +0000 Subject: [PATCH 9/9] Fix wrong parameter order --- view/theme/frio/theme.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/view/theme/frio/theme.php b/view/theme/frio/theme.php index dcbeccc301..4b070e99af 100644 --- a/view/theme/frio/theme.php +++ b/view/theme/frio/theme.php @@ -201,7 +201,7 @@ function frio_remote_nav($a, &$nav) $remoteUser = Contact::getById(remote_user(), $fields); $nav['remote'] = DI::l10n()->t('Guest'); } elseif (Model\Profile::getMyURL()) { - $remoteUser = Contact::getByURL($homelink, $fields); + $remoteUser = Contact::getByURL($homelink, null, $fields); $nav['remote'] = DI::l10n()->t('Visitor'); } else { $remoteUser = null;