From: Hypolite Petovan Date: Mon, 3 Aug 2020 17:10:49 +0000 (-0400) Subject: Move ContactRelation class to Contact\Relation X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=a74c547af470947c3420157cba237c4951da58f4;p=friendica.git Move ContactRelation class to Contact\Relation - Update references in GContact --- diff --git a/src/Model/Contact.php b/src/Model/Contact.php index b6b0fec5d9..3bd826945f 100644 --- a/src/Model/Contact.php +++ b/src/Model/Contact.php @@ -2124,7 +2124,7 @@ class Contact return false; } - if (ContactRelation::isDiscoverable($ret['url'])) { + if (Contact\Relation::isDiscoverable($ret['url'])) { Worker::add(PRIORITY_LOW, 'ContactDiscovery', $ret['url']); } diff --git a/src/Model/Contact/Relation.php b/src/Model/Contact/Relation.php new file mode 100644 index 0000000000..a98f2bfd9a --- /dev/null +++ b/src/Model/Contact/Relation.php @@ -0,0 +1,538 @@ +. + * + */ + +namespace Friendica\Model\Contact; + +use Exception; +use Friendica\Core\Logger; +use Friendica\Core\Protocol; +use Friendica\Database\DBA; +use Friendica\DI; +use Friendica\Protocol\ActivityPub; +use Friendica\Util\DateTimeFormat; +use Friendica\Util\Strings; + +/** + * This class provides relationship information based on the `contact-relation` table. + * This table is directional (cid = source, relation-cid = target), references public contacts (with uid=0) and records both + * follows and the last interaction (likes/comments) on public posts. + */ +class Relation +{ + /** + * No discovery of followers/followings + */ + const DISCOVERY_NONE = 0; + /** + * Discover followers/followings of local contacts + */ + const DISCOVERY_LOCAL = 1; + /** + * Discover followers/followings of local contacts and contacts that visibly interacted on the system + */ + const DISCOVERY_INTERACTOR = 2; + /** + * Discover followers/followings of all contacts + */ + const DISCOVERY_ALL = 3; + + public static function store(int $target, int $actor, string $interaction_date) + { + if ($actor == $target) { + return; + } + + DBA::update('contact-relation', ['last-interaction' => $interaction_date], ['cid' => $target, 'relation-cid' => $actor], true); + } + + /** + * Fetches the followers of a given profile and adds them + * + * @param string $url URL of a profile + * @return void + */ + public static function discoverByUrl(string $url) + { + $contact = Contact::getByURL($url); + if (empty($contact)) { + return; + } + + if (!self::isDiscoverable($url, $contact)) { + return; + } + + $apcontact = APContact::getByURL($url, false); + + if (!empty($apcontact['followers']) && is_string($apcontact['followers'])) { + $followers = ActivityPub::fetchItems($apcontact['followers']); + } else { + $followers = []; + } + + if (!empty($apcontact['following']) && is_string($apcontact['following'])) { + $followings = ActivityPub::fetchItems($apcontact['following']); + } else { + $followings = []; + } + + if (empty($followers) && empty($followings)) { + DBA::update('contact', ['last-discovery' => DateTimeFormat::utcNow()], ['id' => $contact['id']]); + Logger::info('The contact does not offer discoverable data', ['id' => $contact['id'], 'url' => $url, 'network' => $contact['network']]); + return; + } + + $target = $contact['id']; + + if (!empty($followers)) { + // Clear the follower list, since it will be recreated in the next step + DBA::update('contact-relation', ['follows' => false], ['cid' => $target]); + } + + $contacts = []; + foreach (array_merge($followers, $followings) as $contact) { + if (is_string($contact)) { + $contacts[] = $contact; + } elseif (!empty($contact['url']) && is_string($contact['url'])) { + $contacts[] = $contact['url']; + } + } + $contacts = array_unique($contacts); + + $follower_counter = 0; + $following_counter = 0; + + Logger::info('Discover contacts', ['id' => $target, 'url' => $url, 'contacts' => count($contacts)]); + foreach ($contacts as $contact) { + $actor = Contact::getIdForURL($contact); + if (!empty($actor)) { + if (in_array($contact, $followers)) { + $fields = ['cid' => $target, 'relation-cid' => $actor]; + DBA::update('contact-relation', ['follows' => true, 'follow-updated' => DateTimeFormat::utcNow()], $fields, true); + $follower_counter++; + } + + if (in_array($contact, $followings)) { + $fields = ['cid' => $actor, 'relation-cid' => $target]; + DBA::update('contact-relation', ['follows' => true, 'follow-updated' => DateTimeFormat::utcNow()], $fields, true); + $following_counter++; + } + } + } + + if (!empty($followers)) { + // Delete all followers that aren't followers anymore (and aren't interacting) + DBA::delete('contact-relation', ['cid' => $target, 'follows' => false, 'last-interaction' => DBA::NULL_DATETIME]); + } + + DBA::update('contact', ['last-discovery' => DateTimeFormat::utcNow()], ['id' => $target]); + Logger::info('Contacts discovery finished', ['id' => $target, 'url' => $url, 'follower' => $follower_counter, 'following' => $following_counter]); + return; + } + + /** + * Tests if a given contact url is discoverable + * + * @param string $url Contact url + * @param array $contact Contact array + * @return boolean True if contact is discoverable + */ + public static function isDiscoverable(string $url, array $contact = []) + { + $contact_discovery = DI::config()->get('system', 'contact_discovery'); + + if ($contact_discovery == self::DISCOVERY_NONE) { + return false; + } + + if (empty($contact)) { + $contact = Contact::getByURL($url); + } + + if (empty($contact)) { + return false; + } + + if ($contact['last-discovery'] > DateTimeFormat::utc('now - 1 month')) { + Logger::info('No discovery - Last was less than a month ago.', ['id' => $contact['id'], 'url' => $url, 'discovery' => $contact['last-discovery']]); + return false; + } + + if ($contact_discovery != self::DISCOVERY_ALL) { + $local = DBA::exists('contact', ["`nurl` = ? AND `uid` != ?", Strings::normaliseLink($url), 0]); + if (($contact_discovery == self::DISCOVERY_LOCAL) && !$local) { + Logger::info('No discovery - This contact is not followed/following locally.', ['id' => $contact['id'], 'url' => $url]); + return false; + } + + if ($contact_discovery == self::DISCOVERY_INTERACTOR) { + $interactor = DBA::exists('contact-relation', ["`relation-cid` = ? AND `last-interaction` > ?", $contact['id'], DBA::NULL_DATETIME]); + if (!$local && !$interactor) { + Logger::info('No discovery - This contact is not interacting locally.', ['id' => $contact['id'], 'url' => $url]); + return false; + } + } + } elseif ($contact['created'] > DateTimeFormat::utc('now - 1 day')) { + // Newly created contacts are not discovered to avoid DDoS attacks + Logger::info('No discovery - Contact record is less than a day old.', ['id' => $contact['id'], 'url' => $url, 'discovery' => $contact['created']]); + return false; + } + + if (!in_array($contact['network'], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::OSTATUS])) { + $apcontact = APContact::getByURL($url, false); + if (empty($apcontact)) { + Logger::info('No discovery - The contact does not seem to speak ActivityPub.', ['id' => $contact['id'], 'url' => $url, 'network' => $contact['network']]); + return false; + } + } + + return true; + } + + /** + * Counts all the known follows of the provided public contact + * + * @param int $cid Public contact id + * @param array $condition Additional condition on the contact table + * @return int + * @throws Exception + */ + public static function countFollows(int $cid, array $condition = []) + { + $condition = DBA::mergeConditions($condition, + ['`id` IN ( + SELECT `relation-cid` + FROM `contact-relation` + WHERE `cid` = ? + AND `follows` +)', $cid] + ); + + return DI::dba()->count('contact', $condition); + } + + /** + * Returns a paginated list of contacts that are followed the provided public contact. + * + * @param int $cid Public contact id + * @param array $condition Additional condition on the contact table + * @param int $count + * @param int $offset + * @param bool $shuffle + * @return array + * @throws Exception + */ + public static function listFollows(int $cid, array $condition = [], int $count = 30, int $offset = 0, bool $shuffle = false) + { + $condition = DBA::mergeConditions($condition, + ['`id` IN ( + SELECT `relation-cid` + FROM `contact-relation` + WHERE `cid` = ? + AND `follows` +)', $cid] + ); + + $follows = DI::dba()->selectToArray( + 'contact', + $condition, + [ + 'limit' => [$offset, $count], + 'order' => [$shuffle ? 'RAND()' : 'name'] + ] + ); + + return $follows; + } + + /** + * Counts all the known followers of the provided public contact + * + * @param int $cid Public contact id + * @param array $condition Additional condition on the contact table + * @return int + * @throws Exception + */ + public static function countFollowers(int $cid, array $condition = []) + { + $condition = DBA::mergeConditions($condition, + ['`id` IN ( + SELECT `cid` + FROM `contact-relation` + WHERE `relation-cid` = ? + AND `follows` +)', $cid] + ); + + return DI::dba()->count('contact', $condition); + } + + /** + * Returns a paginated list of contacts that follow the provided public contact. + * + * @param int $cid Public contact id + * @param array $condition Additional condition on the contact table + * @param int $count + * @param int $offset + * @param bool $shuffle + * @return array + * @throws Exception + */ + public static function listFollowers(int $cid, array $condition = [], int $count = 30, int $offset = 0, bool $shuffle = false) + { + $condition = DBA::mergeConditions($condition, + ['`id` IN ( + SELECT `cid` + FROM `contact-relation` + WHERE `relation-cid` = ? + AND `follows` +)', $cid] + ); + + $followers = DI::dba()->selectToArray( + 'contact', + $condition, + [ + 'limit' => [$offset, $count], + 'order' => [$shuffle ? 'RAND()' : 'name'] + ] + ); + + return $followers; + } + + /** + * Counts the number of contacts that both provided public contacts have interacted with at least once. + * Interactions include follows and likes and comments on public posts. + * + * @param int $sourceId Public contact id + * @param int $targetId Public contact id + * @param array $condition Additional condition array on the contact table + * @return int + * @throws Exception + */ + public static function countCommon(int $sourceId, int $targetId, array $condition = []) + { + $condition = DBA::mergeConditions($condition, + ['`id` IN ( + SELECT `relation-cid` + FROM `contact-relation` + WHERE `cid` = ? +) + AND `id` IN ( + SELECT `relation-cid` + FROM `contact-relation` + WHERE `cid` = ? +)', $sourceId, $targetId] + ); + + $total = DI::dba()->count('contact', $condition); + + return $total; + } + + /** + * Returns a paginated list of contacts that both provided public contacts have interacted with at least once. + * Interactions include follows and likes and comments on public posts. + * + * @param int $sourceId Public contact id + * @param int $targetId Public contact id + * @param array $condition Additional condition on the contact table + * @param int $count + * @param int $offset + * @param bool $shuffle + * @return array + * @throws Exception + */ + public static function listCommon(int $sourceId, int $targetId, array $condition = [], int $count = 30, int $offset = 0, bool $shuffle = false) + { + $condition = DBA::mergeConditions($condition, + ["`id` IN ( + SELECT `relation-cid` + FROM `contact-relation` + WHERE `cid` = ? + AND `follows` +) + AND `id` IN ( + SELECT `relation-cid` + FROM `contact-relation` + WHERE `cid` = ? + AND `follows` +)", $sourceId, $targetId] + ); + + $contacts = DI::dba()->selectToArray( + 'contact', + $condition, + [ + 'limit' => [$offset, $count], + 'order' => [$shuffle ? 'name' : 'RAND()'], + ] + ); + + return $contacts; + } + + + /** + * Counts the number of contacts that are followed by both provided public contacts. + * + * @param int $sourceId Public contact id + * @param int $targetId Public contact id + * @param array $condition Additional condition array on the contact table + * @return int + * @throws Exception + */ + public static function countCommonFollows(int $sourceId, int $targetId, array $condition = []) + { + $condition = DBA::mergeConditions($condition, + ['`id` IN ( + SELECT `relation-cid` + FROM `contact-relation` + WHERE `cid` = ? + AND `follows` +) + AND `id` IN ( + SELECT `relation-cid` + FROM `contact-relation` + WHERE `cid` = ? + AND `follows` +)', $sourceId, $targetId] + ); + + $total = DI::dba()->count('contact', $condition); + + return $total; + } + + /** + * Returns a paginated list of contacts that are followed by both provided public contacts. + * + * @param int $sourceId Public contact id + * @param int $targetId Public contact id + * @param array $condition Additional condition array on the contact table + * @param int $count + * @param int $offset + * @param bool $shuffle + * @return array + * @throws Exception + */ + public static function listCommonFollows(int $sourceId, int $targetId, array $condition = [], int $count = 30, int $offset = 0, bool $shuffle = false) + { + $condition = DBA::mergeConditions($condition, + ["`id` IN ( + SELECT `relation-cid` + FROM `contact-relation` + WHERE `cid` = ? + AND `follows` +) + AND `id` IN ( + SELECT `relation-cid` + FROM `contact-relation` + WHERE `cid` = ? + AND `follows` +)", $sourceId, $targetId] + ); + + $contacts = DI::dba()->selectToArray( + 'contact', + $condition, + [ + 'limit' => [$offset, $count], + 'order' => [$shuffle ? 'name' : 'RAND()'], + ] + ); + + return $contacts; + } + + /** + * Counts the number of contacts that follow both provided public contacts. + * + * @param int $sourceId Public contact id + * @param int $targetId Public contact id + * @param array $condition Additional condition on the contact table + * @return int + * @throws Exception + */ + public static function countCommonFollowers(int $sourceId, int $targetId, array $condition = []) + { + $condition = DBA::mergeConditions($condition, + ['`id` IN ( + SELECT `cid` + FROM `contact-relation` + WHERE `relation-cid` = ? + AND `follows` +) + AND `id` IN ( + SELECT `cid` + FROM `contact-relation` + WHERE `relation-cid` = ? + AND `follows` +)', $sourceId, $targetId] + ); + + $total = DI::dba()->count('contact', $condition); + + return $total; + } + + /** + * Returns a paginated list of contacts that follow both provided public contacts. + * + * @param int $sourceId Public contact id + * @param int $targetId Public contact id + * @param array $condition Additional condition on the contact table + * @param int $count + * @param int $offset + * @param bool $shuffle + * @return array + * @throws Exception + */ + public static function listCommonFollowers(int $sourceId, int $targetId, array $condition = [], int $count = 30, int $offset = 0, bool $shuffle = false) + { + $condition = DBA::mergeConditions($condition, + ["`id` IN ( + SELECT `cid` + FROM `contact-relation` + WHERE `relation-cid` = ? + AND `follows` +) + AND `id` IN ( + SELECT `cid` + FROM `contact-relation` + WHERE `relation-cid` = ? + AND `follows` +)", $sourceId, $targetId] + ); + + $contacts = DI::dba()->selectToArray( + 'contact', + $condition, + [ + 'limit' => [$offset, $count], + 'order' => [$shuffle ? 'name' : 'RAND()'], + ] + ); + + return $contacts; + } +} diff --git a/src/Model/ContactRelation.php b/src/Model/ContactRelation.php deleted file mode 100644 index 85dbc93b9b..0000000000 --- a/src/Model/ContactRelation.php +++ /dev/null @@ -1,538 +0,0 @@ -. - * - */ - -namespace Friendica\Model; - -use Exception; -use Friendica\Core\Logger; -use Friendica\Core\Protocol; -use Friendica\Database\DBA; -use Friendica\DI; -use Friendica\Protocol\ActivityPub; -use Friendica\Util\DateTimeFormat; -use Friendica\Util\Strings; - -/** - * This class provides relationship information based on the `contact-relation` table. - * This table is directional (cid = source, relation-cid = target), references public contacts (with uid=0) and records both - * follows and the last interaction (likes/comments) on public posts. - */ -class ContactRelation -{ - /** - * No discovery of followers/followings - */ - const DISCOVERY_NONE = 0; - /** - * Discover followers/followings of local contacts - */ - const DISCOVERY_LOCAL = 1; - /** - * Discover followers/followings of local contacts and contacts that visibly interacted on the system - */ - const DISCOVERY_INTERACTOR = 2; - /** - * Discover followers/followings of all contacts - */ - const DISCOVERY_ALL = 3; - - public static function store(int $target, int $actor, string $interaction_date) - { - if ($actor == $target) { - return; - } - - DBA::update('contact-relation', ['last-interaction' => $interaction_date], ['cid' => $target, 'relation-cid' => $actor], true); - } - - /** - * Fetches the followers of a given profile and adds them - * - * @param string $url URL of a profile - * @return void - */ - public static function discoverByUrl(string $url) - { - $contact = Contact::getByURL($url); - if (empty($contact)) { - return; - } - - if (!self::isDiscoverable($url, $contact)) { - return; - } - - $apcontact = APContact::getByURL($url, false); - - if (!empty($apcontact['followers']) && is_string($apcontact['followers'])) { - $followers = ActivityPub::fetchItems($apcontact['followers']); - } else { - $followers = []; - } - - if (!empty($apcontact['following']) && is_string($apcontact['following'])) { - $followings = ActivityPub::fetchItems($apcontact['following']); - } else { - $followings = []; - } - - if (empty($followers) && empty($followings)) { - DBA::update('contact', ['last-discovery' => DateTimeFormat::utcNow()], ['id' => $contact['id']]); - Logger::info('The contact does not offer discoverable data', ['id' => $contact['id'], 'url' => $url, 'network' => $contact['network']]); - return; - } - - $target = $contact['id']; - - if (!empty($followers)) { - // Clear the follower list, since it will be recreated in the next step - DBA::update('contact-relation', ['follows' => false], ['cid' => $target]); - } - - $contacts = []; - foreach (array_merge($followers, $followings) as $contact) { - if (is_string($contact)) { - $contacts[] = $contact; - } elseif (!empty($contact['url']) && is_string($contact['url'])) { - $contacts[] = $contact['url']; - } - } - $contacts = array_unique($contacts); - - $follower_counter = 0; - $following_counter = 0; - - Logger::info('Discover contacts', ['id' => $target, 'url' => $url, 'contacts' => count($contacts)]); - foreach ($contacts as $contact) { - $actor = Contact::getIdForURL($contact); - if (!empty($actor)) { - if (in_array($contact, $followers)) { - $fields = ['cid' => $target, 'relation-cid' => $actor]; - DBA::update('contact-relation', ['follows' => true, 'follow-updated' => DateTimeFormat::utcNow()], $fields, true); - $follower_counter++; - } - - if (in_array($contact, $followings)) { - $fields = ['cid' => $actor, 'relation-cid' => $target]; - DBA::update('contact-relation', ['follows' => true, 'follow-updated' => DateTimeFormat::utcNow()], $fields, true); - $following_counter++; - } - } - } - - if (!empty($followers)) { - // Delete all followers that aren't followers anymore (and aren't interacting) - DBA::delete('contact-relation', ['cid' => $target, 'follows' => false, 'last-interaction' => DBA::NULL_DATETIME]); - } - - DBA::update('contact', ['last-discovery' => DateTimeFormat::utcNow()], ['id' => $target]); - Logger::info('Contacts discovery finished', ['id' => $target, 'url' => $url, 'follower' => $follower_counter, 'following' => $following_counter]); - return; - } - - /** - * Tests if a given contact url is discoverable - * - * @param string $url Contact url - * @param array $contact Contact array - * @return boolean True if contact is discoverable - */ - public static function isDiscoverable(string $url, array $contact = []) - { - $contact_discovery = DI::config()->get('system', 'contact_discovery'); - - if ($contact_discovery == self::DISCOVERY_NONE) { - return false; - } - - if (empty($contact)) { - $contact = Contact::getByURL($url); - } - - if (empty($contact)) { - return false; - } - - if ($contact['last-discovery'] > DateTimeFormat::utc('now - 1 month')) { - Logger::info('No discovery - Last was less than a month ago.', ['id' => $contact['id'], 'url' => $url, 'discovery' => $contact['last-discovery']]); - return false; - } - - if ($contact_discovery != self::DISCOVERY_ALL) { - $local = DBA::exists('contact', ["`nurl` = ? AND `uid` != ?", Strings::normaliseLink($url), 0]); - if (($contact_discovery == self::DISCOVERY_LOCAL) && !$local) { - Logger::info('No discovery - This contact is not followed/following locally.', ['id' => $contact['id'], 'url' => $url]); - return false; - } - - if ($contact_discovery == self::DISCOVERY_INTERACTOR) { - $interactor = DBA::exists('contact-relation', ["`relation-cid` = ? AND `last-interaction` > ?", $contact['id'], DBA::NULL_DATETIME]); - if (!$local && !$interactor) { - Logger::info('No discovery - This contact is not interacting locally.', ['id' => $contact['id'], 'url' => $url]); - return false; - } - } - } elseif ($contact['created'] > DateTimeFormat::utc('now - 1 day')) { - // Newly created contacts are not discovered to avoid DDoS attacks - Logger::info('No discovery - Contact record is less than a day old.', ['id' => $contact['id'], 'url' => $url, 'discovery' => $contact['created']]); - return false; - } - - if (!in_array($contact['network'], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::OSTATUS])) { - $apcontact = APContact::getByURL($url, false); - if (empty($apcontact)) { - Logger::info('No discovery - The contact does not seem to speak ActivityPub.', ['id' => $contact['id'], 'url' => $url, 'network' => $contact['network']]); - return false; - } - } - - return true; - } - - /** - * Counts all the known follows of the provided public contact - * - * @param int $cid Public contact id - * @param array $condition Additional condition on the contact table - * @return int - * @throws Exception - */ - public static function countFollows(int $cid, array $condition = []) - { - $condition = DBA::mergeConditions($condition, - ['`id` IN ( - SELECT `relation-cid` - FROM `contact-relation` - WHERE `cid` = ? - AND `follows` -)', $cid] - ); - - return DI::dba()->count('contact', $condition); - } - - /** - * Returns a paginated list of contacts that are followed the provided public contact. - * - * @param int $cid Public contact id - * @param array $condition Additional condition on the contact table - * @param int $count - * @param int $offset - * @param bool $shuffle - * @return array - * @throws Exception - */ - public static function listFollows(int $cid, array $condition = [], int $count = 30, int $offset = 0, bool $shuffle = false) - { - $condition = DBA::mergeConditions($condition, - ['`id` IN ( - SELECT `relation-cid` - FROM `contact-relation` - WHERE `cid` = ? - AND `follows` -)', $cid] - ); - - $follows = DI::dba()->selectToArray( - 'contact', - $condition, - [ - 'limit' => [$offset, $count], - 'order' => [$shuffle ? 'RAND()' : 'name'] - ] - ); - - return $follows; - } - - /** - * Counts all the known followers of the provided public contact - * - * @param int $cid Public contact id - * @param array $condition Additional condition on the contact table - * @return int - * @throws Exception - */ - public static function countFollowers(int $cid, array $condition = []) - { - $condition = DBA::mergeConditions($condition, - ['`id` IN ( - SELECT `cid` - FROM `contact-relation` - WHERE `relation-cid` = ? - AND `follows` -)', $cid] - ); - - return DI::dba()->count('contact', $condition); - } - - /** - * Returns a paginated list of contacts that follow the provided public contact. - * - * @param int $cid Public contact id - * @param array $condition Additional condition on the contact table - * @param int $count - * @param int $offset - * @param bool $shuffle - * @return array - * @throws Exception - */ - public static function listFollowers(int $cid, array $condition = [], int $count = 30, int $offset = 0, bool $shuffle = false) - { - $condition = DBA::mergeConditions($condition, - ['`id` IN ( - SELECT `cid` - FROM `contact-relation` - WHERE `relation-cid` = ? - AND `follows` -)', $cid] - ); - - $followers = DI::dba()->selectToArray( - 'contact', - $condition, - [ - 'limit' => [$offset, $count], - 'order' => [$shuffle ? 'RAND()' : 'name'] - ] - ); - - return $followers; - } - - /** - * Counts the number of contacts that both provided public contacts have interacted with at least once. - * Interactions include follows and likes and comments on public posts. - * - * @param int $sourceId Public contact id - * @param int $targetId Public contact id - * @param array $condition Additional condition array on the contact table - * @return int - * @throws Exception - */ - public static function countCommon(int $sourceId, int $targetId, array $condition = []) - { - $condition = DBA::mergeConditions($condition, - ['`id` IN ( - SELECT `relation-cid` - FROM `contact-relation` - WHERE `cid` = ? -) - AND `id` IN ( - SELECT `relation-cid` - FROM `contact-relation` - WHERE `cid` = ? -)', $sourceId, $targetId] - ); - - $total = DI::dba()->count('contact', $condition); - - return $total; - } - - /** - * Returns a paginated list of contacts that both provided public contacts have interacted with at least once. - * Interactions include follows and likes and comments on public posts. - * - * @param int $sourceId Public contact id - * @param int $targetId Public contact id - * @param array $condition Additional condition on the contact table - * @param int $count - * @param int $offset - * @param bool $shuffle - * @return array - * @throws Exception - */ - public static function listCommon(int $sourceId, int $targetId, array $condition = [], int $count = 30, int $offset = 0, bool $shuffle = false) - { - $condition = DBA::mergeConditions($condition, - ["`id` IN ( - SELECT `relation-cid` - FROM `contact-relation` - WHERE `cid` = ? - AND `follows` -) - AND `id` IN ( - SELECT `relation-cid` - FROM `contact-relation` - WHERE `cid` = ? - AND `follows` -)", $sourceId, $targetId] - ); - - $contacts = DI::dba()->selectToArray( - 'contact', - $condition, - [ - 'limit' => [$offset, $count], - 'order' => [$shuffle ? 'name' : 'RAND()'], - ] - ); - - return $contacts; - } - - - /** - * Counts the number of contacts that are followed by both provided public contacts. - * - * @param int $sourceId Public contact id - * @param int $targetId Public contact id - * @param array $condition Additional condition array on the contact table - * @return int - * @throws Exception - */ - public static function countCommonFollows(int $sourceId, int $targetId, array $condition = []) - { - $condition = DBA::mergeConditions($condition, - ['`id` IN ( - SELECT `relation-cid` - FROM `contact-relation` - WHERE `cid` = ? - AND `follows` -) - AND `id` IN ( - SELECT `relation-cid` - FROM `contact-relation` - WHERE `cid` = ? - AND `follows` -)', $sourceId, $targetId] - ); - - $total = DI::dba()->count('contact', $condition); - - return $total; - } - - /** - * Returns a paginated list of contacts that are followed by both provided public contacts. - * - * @param int $sourceId Public contact id - * @param int $targetId Public contact id - * @param array $condition Additional condition array on the contact table - * @param int $count - * @param int $offset - * @param bool $shuffle - * @return array - * @throws Exception - */ - public static function listCommonFollows(int $sourceId, int $targetId, array $condition = [], int $count = 30, int $offset = 0, bool $shuffle = false) - { - $condition = DBA::mergeConditions($condition, - ["`id` IN ( - SELECT `relation-cid` - FROM `contact-relation` - WHERE `cid` = ? - AND `follows` -) - AND `id` IN ( - SELECT `relation-cid` - FROM `contact-relation` - WHERE `cid` = ? - AND `follows` -)", $sourceId, $targetId] - ); - - $contacts = DI::dba()->selectToArray( - 'contact', - $condition, - [ - 'limit' => [$offset, $count], - 'order' => [$shuffle ? 'name' : 'RAND()'], - ] - ); - - return $contacts; - } - - /** - * Counts the number of contacts that follow both provided public contacts. - * - * @param int $sourceId Public contact id - * @param int $targetId Public contact id - * @param array $condition Additional condition on the contact table - * @return int - * @throws Exception - */ - public static function countCommonFollowers(int $sourceId, int $targetId, array $condition = []) - { - $condition = DBA::mergeConditions($condition, - ['`id` IN ( - SELECT `cid` - FROM `contact-relation` - WHERE `relation-cid` = ? - AND `follows` -) - AND `id` IN ( - SELECT `cid` - FROM `contact-relation` - WHERE `relation-cid` = ? - AND `follows` -)', $sourceId, $targetId] - ); - - $total = DI::dba()->count('contact', $condition); - - return $total; - } - - /** - * Returns a paginated list of contacts that follow both provided public contacts. - * - * @param int $sourceId Public contact id - * @param int $targetId Public contact id - * @param array $condition Additional condition on the contact table - * @param int $count - * @param int $offset - * @param bool $shuffle - * @return array - * @throws Exception - */ - public static function listCommonFollowers(int $sourceId, int $targetId, array $condition = [], int $count = 30, int $offset = 0, bool $shuffle = false) - { - $condition = DBA::mergeConditions($condition, - ["`id` IN ( - SELECT `cid` - FROM `contact-relation` - WHERE `relation-cid` = ? - AND `follows` -) - AND `id` IN ( - SELECT `cid` - FROM `contact-relation` - WHERE `relation-cid` = ? - AND `follows` -)", $sourceId, $targetId] - ); - - $contacts = DI::dba()->selectToArray( - 'contact', - $condition, - [ - 'limit' => [$offset, $count], - 'order' => [$shuffle ? 'name' : 'RAND()'], - ] - ); - - return $contacts; - } -} diff --git a/src/Model/GContact.php b/src/Model/GContact.php index 55749d3b19..3051202689 100644 --- a/src/Model/GContact.php +++ b/src/Model/GContact.php @@ -24,6 +24,7 @@ namespace Friendica\Model; use Exception; use Friendica\Core\Protocol; use Friendica\Database\DBA; +use Friendica\DI; use Friendica\Util\DateTimeFormat; /** @@ -48,7 +49,7 @@ class GContact $sourceId, ]; - return ContactRelation::countCommonFollows($sourceId, $targetIds['public'] ?? 0, $condition); + return Contact\Relation::countCommonFollows($sourceId, $targetIds['public'] ?? 0, $condition); } /** @@ -71,7 +72,12 @@ LIMIT 1", $zcid ); - return ContactRelation::countCommonFollowers($sourceId, $targetPublicContact['id'] ?? 0); + $condition = [ + 'NOT `self` AND NOT `blocked` AND NOT `hidden` AND `id` != ?', + $sourceId, + ]; + + return Contact\Relation::countCommonFollowers($sourceId, $targetPublicContact['id'] ?? 0, $condition); } /** @@ -97,7 +103,7 @@ LIMIT 1", $sourceId, ]; - return ContactRelation::listCommonFollows($sourceId, $targetIds['public'] ?? 0, $condition, $limit, $start, $shuffle); + return Contact\Relation::listCommonFollows($sourceId, $targetIds['public'] ?? 0, $condition, $limit, $start, $shuffle); } /** @@ -126,7 +132,12 @@ LIMIT 1", $zcid ); - return ContactRelation::listCommonFollows($sourceId, $targetPublicContact['id'] ?? 0, [], $limit, $start, $shuffle); + $condition = [ + 'NOT `self` AND NOT `blocked` AND NOT `hidden` AND `id` != ?', + $sourceId, + ]; + + return Contact\Relation::listCommonFollows($sourceId, $targetPublicContact['id'] ?? 0, $condition, $limit, $start, $shuffle); } /** @@ -139,7 +150,7 @@ LIMIT 1", { $cids = Contact::getPublicAndUserContacID($cid, $uid); - return ContactRelation::countFollows($cids['public'] ?? 0); + return Contact\Relation::countFollows($cids['public'] ?? 0); } /** @@ -154,6 +165,6 @@ LIMIT 1", { $cids = Contact::getPublicAndUserContacID($cid, $uid); - return ContactRelation::listFollows($cids['public'] ?? 0, [], $limit, $start); + return Contact\Relation::listFollows($cids['public'] ?? 0, [], $limit, $start); } } diff --git a/src/Model/Item.php b/src/Model/Item.php index b6f8ffa3d1..54cd4a5db6 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -1554,7 +1554,7 @@ class Item } // Update the contact relations - ContactRelation::store($parent['author-id'], $item['author-id'], $item['created']); + Contact\Relation::store($parent['author-id'], $item['author-id'], $item['created']); } return $item; diff --git a/src/Module/Admin/Site.php b/src/Module/Admin/Site.php index 7b298cd937..50566b349f 100644 --- a/src/Module/Admin/Site.php +++ b/src/Module/Admin/Site.php @@ -28,7 +28,7 @@ use Friendica\Core\Theme; use Friendica\Core\Worker; use Friendica\Database\DBA; use Friendica\DI; -use Friendica\Model\ContactRelation; +use Friendica\Model\Contact; use Friendica\Module\BaseAdmin; use Friendica\Module\Register; use Friendica\Util\BasePath; @@ -175,7 +175,7 @@ class Site extends BaseAdmin $min_memory = (!empty($_POST['min_memory']) ? intval(trim($_POST['min_memory'])) : 0); $optimize_max_tablesize = (!empty($_POST['optimize_max_tablesize']) ? intval(trim($_POST['optimize_max_tablesize'])) : 100); $optimize_fragmentation = (!empty($_POST['optimize_fragmentation']) ? intval(trim($_POST['optimize_fragmentation'])) : 30); - $contact_discovery = (!empty($_POST['contact_discovery']) ? intval(trim($_POST['contact_discovery'])) : ContactRelation::DISCOVERY_NONE); + $contact_discovery = (!empty($_POST['contact_discovery']) ? intval(trim($_POST['contact_discovery'])) : Contact\Relation::DISCOVERY_NONE); $synchronize_directory = (!empty($_POST['synchronize_directory']) ? intval(trim($_POST['synchronize_directory'])) : false); $poco_requery_days = (!empty($_POST['poco_requery_days']) ? intval(trim($_POST['poco_requery_days'])) : 7); $poco_discovery = (!empty($_POST['poco_discovery']) ? intval(trim($_POST['poco_discovery'])) : false); @@ -532,9 +532,9 @@ class Site extends BaseAdmin ]; $discovery_choices = [ - ContactRelation::DISCOVERY_NONE => DI::l10n()->t('none'), - ContactRelation::DISCOVERY_LOCAL => DI::l10n()->t('Local contacts'), - ContactRelation::DISCOVERY_INTERACTOR => DI::l10n()->t('Interactors'), + Contact\Relation::DISCOVERY_NONE => DI::l10n()->t('none'), + Contact\Relation::DISCOVERY_LOCAL => DI::l10n()->t('Local contacts'), + Contact\Relation::DISCOVERY_INTERACTOR => DI::l10n()->t('Interactors'), // "All" is deactivated until we are sure not to put too much stress on the fediverse with this // ContactRelation::DISCOVERY_ALL => DI::l10n()->t('All'), ]; diff --git a/src/Worker/ContactDiscovery.php b/src/Worker/ContactDiscovery.php index 34d4a7da0a..5dac173228 100644 --- a/src/Worker/ContactDiscovery.php +++ b/src/Worker/ContactDiscovery.php @@ -21,7 +21,7 @@ namespace Friendica\Worker; -use Friendica\Model\ContactRelation; +use Friendica\Model\Contact; class ContactDiscovery { @@ -31,6 +31,6 @@ class ContactDiscovery */ public static function execute(string $url) { - ContactRelation::discoverByUrl($url); + Contact\Relation::discoverByUrl($url); } }