+ $fields = ['last_contact' => DateTimeFormat::utcNow(), 'updated' => $last_updated];
+ DBA::update('gcontact', $fields, ['nurl' => Strings::normaliseLink($data['url'])]);
+ }
+ /**
+ * @brief Updates the gcontact entry from a given public contact id
+ *
+ * @param integer $cid contact id
+ * @return void
+ * @throws \Friendica\Network\HTTPException\InternalServerErrorException
+ * @throws \ImagickException
+ */
+ public static function updateFromPublicContactID($cid)
+ {
+ self::updateFromPublicContact(['id' => $cid]);
+ }
+
+ /**
+ * @brief Updates the gcontact entry from a given public contact url
+ *
+ * @param string $url contact url
+ * @return integer gcontact id
+ * @throws \Friendica\Network\HTTPException\InternalServerErrorException
+ * @throws \ImagickException
+ */
+ public static function updateFromPublicContactURL($url)
+ {
+ return self::updateFromPublicContact(['nurl' => Strings::normaliseLink($url)]);
+ }
+
+ /**
+ * @brief Helper function for updateFromPublicContactID and updateFromPublicContactURL
+ *
+ * @param array $condition contact condition
+ * @return integer gcontact id
+ * @throws \Friendica\Network\HTTPException\InternalServerErrorException
+ * @throws \ImagickException
+ */
+ private static function updateFromPublicContact($condition)
+ {
+ $fields = ['name', 'nick', 'url', 'nurl', 'location', 'about', 'keywords', 'gender',
+ 'bd', 'contact-type', 'network', 'addr', 'notify', 'alias', 'archive', 'term-date',
+ 'created', 'updated', 'avatar', 'success_update', 'failure_update', 'forum', 'prv',
+ 'baseurl', 'sensitive', 'unsearchable'];
+
+ $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',
+ 'birthday', 'contact-type', 'network', 'addr', 'notify', 'alias', 'archived', 'archive_date',
+ 'created', 'updated', 'photo', 'last_contact', 'last_failure', 'community', 'connect',
+ 'server_url', 'nsfw', 'hide', 'id'];
+
+ $old_gcontact = DBA::selectFirst('gcontact', $fields, ['nurl' => $contact['nurl']]);
+ $do_insert = !DBA::isResult($old_gcontact);
+ if ($do_insert) {
+ $old_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'];
+
+ foreach ($fields as $field) {
+ $gcontact[$field] = $contact[$field];
+ }
+
+ // These fields are having different names but the same content
+ $gcontact['server_url'] = $contact['baseurl'] ?? ''; // "baseurl" can be null, "server_url" not
+ $gcontact['nsfw'] = $contact['sensitive'];
+ $gcontact['hide'] = $contact['unsearchable'];
+ $gcontact['archived'] = $contact['archive'];
+ $gcontact['archive_date'] = $contact['term-date'];
+ $gcontact['birthday'] = $contact['bd'];
+ $gcontact['photo'] = $contact['avatar'];
+ $gcontact['last_contact'] = $contact['success_update'];
+ $gcontact['last_failure'] = $contact['failure_update'];
+ $gcontact['community'] = ($contact['forum'] || $contact['prv']);
+
+ foreach (['last_contact', 'last_failure', 'updated'] as $field) {
+ if (!empty($old_gcontact[$field]) && ($old_gcontact[$field] >= $gcontact[$field])) {
+ unset($gcontact[$field]);
+ }
+ }
+
+ if (!$gcontact['archived']) {
+ $gcontact['archive_date'] = DBA::NULL_DATETIME;
+ }
+
+ if (!empty($old_gcontact['created']) && ($old_gcontact['created'] > DBA::NULL_DATETIME)
+ && ($old_gcontact['created'] <= $gcontact['created'])) {
+ unset($gcontact['created']);
+ }
+
+ if (empty($gcontact['birthday']) && ($gcontact['birthday'] <= DBA::NULL_DATETIME)) {
+ unset($gcontact['birthday']);
+ }
+
+ if (empty($old_gcontact['generation']) || ($old_gcontact['generation'] > 2)) {
+ $gcontact['generation'] = 2; // We fetched the data directly from the other server
+ }
+
+ if (!$do_insert) {
+ DBA::update('gcontact', $gcontact, ['nurl' => $contact['nurl']], $old_gcontact);
+ return $old_gcontact['id'];
+ } elseif (!$gcontact['archived']) {
+ DBA::insert('gcontact', $gcontact);
+ return DBA::lastInsertId();
+ }
+ }
+
+ /**
+ * @brief Updates the gcontact entry from probe
+ *
+ * @param string $url profile link
+ * @param boolean $force Optional forcing of network probing (otherwise we use the cached data)
+ *
+ * @return boolean 'true' when contact had been updated
+ *
+ * @throws \Friendica\Network\HTTPException\InternalServerErrorException
+ * @throws \ImagickException
+ */
+ public static function updateFromProbe($url, $force = false)
+ {
+ $data = Probe::uri($url, $force);
+
+ if (in_array($data['network'], [Protocol::PHANTOM])) {
+ $fields = ['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;
+ }
+