From 338ddf45b1bec3ea102f2b2388c887181af0d9d4 Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 22 Sep 2020 05:36:01 +0000 Subject: [PATCH 1/3] We now store the causer-id in the items --- database.sql | 3 +- include/conversation.php | 57 ++++++-------------------- src/Model/Item.php | 20 ++++++--- src/Protocol/ActivityPub/Processor.php | 14 ++++--- static/dbstructure.config.php | 3 +- 5 files changed, 40 insertions(+), 57 deletions(-) diff --git a/database.sql b/database.sql index fe957552e7..499ac3b033 100644 --- a/database.sql +++ b/database.sql @@ -1,6 +1,6 @@ -- ------------------------------------------ -- Friendica 2020.12-dev (Red Hot Poker) --- DB_UPDATE_VERSION 1368 +-- DB_UPDATE_VERSION 1369 -- ------------------------------------------ @@ -654,6 +654,7 @@ CREATE TABLE IF NOT EXISTS `item` ( `network` char(4) NOT NULL DEFAULT '' COMMENT 'Network from where the item comes from', `owner-id` int unsigned NOT NULL DEFAULT 0 COMMENT 'Link to the contact table with uid=0 of the owner of this item', `author-id` int unsigned NOT NULL DEFAULT 0 COMMENT 'Link to the contact table with uid=0 of the author of this item', + `causer-id` int unsigned NOT NULL DEFAULT 0 COMMENT 'Link to the contact table with uid=0 of the contact that caused the item creation', `icid` int unsigned COMMENT 'Id of the item-content table entry that contains the whole item content', `iaid` int unsigned COMMENT 'Id of the item-activity table entry that contains the activity data', `vid` smallint unsigned COMMENT 'Id of the verb table entry that contains the activity verbs', diff --git a/include/conversation.php b/include/conversation.php index b25fae4f71..ed6710bdf7 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -708,30 +708,9 @@ function conversation(App $a, array $items, $mode, $update, $preview = false, $o */ function conversation_fetch_comments($thread_items, $pinned) { $comments = []; - $parentlines = []; - $lineno = 0; - $direction = []; - $actor = []; - $received = ''; while ($row = Item::fetch($thread_items)) { - if (!empty($parentlines) && ($row['verb'] == Activity::ANNOUNCE) - && ($row['thr-parent'] == $row['parent-uri']) && ($row['received'] > $received) - && Contact::isSharing($row['author-id'], $row['uid'])) { - $direction = ['direction' => 3, 'title' => DI::l10n()->t('%s reshared this.', $row['author-name'])]; - - $author = ['uid' => 0, 'id' => $row['author-id'], - 'network' => $row['author-network'], 'url' => $row['author-link']]; - $url = '' . htmlentities($row['author-name']) . ''; - - $actor = ['url' => $url, 'link' => $row['author-link'], 'avatar' => $row['author-avatar'], 'name' => $row['author-name']]; - $received = $row['received']; - } - - if (!empty($parentlines) && empty($direction) && ($row['gravity'] == GRAVITY_COMMENT) - && Contact::isSharing($row['author-id'], $row['uid'])) { - $direction = ['direction' => 5, 'title' => DI::l10n()->t('%s commented on this.', $row['author-name'])]; - } + $name = $row['causer-contact-type'] == Contact::TYPE_RELAY ? $row['causer-link'] : $row['causer-name']; switch ($row['post-type']) { case Item::PT_TO: @@ -753,7 +732,16 @@ function conversation_fetch_comments($thread_items, $pinned) { $row['direction'] = ['direction' => 4, 'title' => DI::l10n()->t('Tagged')]; break; case Item::PT_ANNOUNCEMENT: - $row['direction'] = ['direction' => 3, 'title' => DI::l10n()->t('Reshared')]; + if (!empty($row['causer-id']) && DI::pConfig()->get(local_user(), 'system', 'display_resharer') ) { + $row['owner-link'] = $row['causer-link']; + $row['owner-avatar'] = $row['causer-avatar']; + $row['owner-name'] = $row['causer-name']; + } + + if (($row['gravity'] == GRAVITY_PARENT) && !empty($row['causer-id'])) { + $row['reshared'] = DI::l10n()->t('%s reshared this.', '' . htmlentities($name) . ''); + } + $row['direction'] = ['direction' => 3, 'title' => (empty($row['causer-id']) ? DI::l10n()->t('Reshared') : DI::l10n()->t('Reshared by %s', $name))]; break; case Item::PT_COMMENT: $row['direction'] = ['direction' => 5, 'title' => DI::l10n()->t('%s is participating in this thread.', $row['author-name'])]; @@ -765,41 +753,22 @@ function conversation_fetch_comments($thread_items, $pinned) { $row['direction'] = ['direction' => 9, 'title' => DI::l10n()->t('Global')]; break; case Item::PT_RELAY: - $row['direction'] = ['direction' => 10, 'title' => DI::l10n()->t('Relay')]; + $row['direction'] = ['direction' => 10, 'title' => (empty($row['causer-id']) ? DI::l10n()->t('Relayed') : DI::l10n()->t('Relayed by %s.', $name))]; break; case Item::PT_FETCHED: - $row['direction'] = ['direction' => 2, 'title' => DI::l10n()->t('Fetched')]; + $row['direction'] = ['direction' => 2, 'title' => (empty($row['causer-id']) ? DI::l10n()->t('Fetched') : DI::l10n()->t('Fetched because of %s', $name))]; break; } - if (($row['gravity'] == GRAVITY_PARENT) && !$row['origin'] && ($row['author-id'] == $row['owner-id']) && - !Contact::isSharing($row['author-id'], $row['uid'])) { - $parentlines[] = $lineno; - } - if ($row['gravity'] == GRAVITY_PARENT) { $row['pinned'] = $pinned; } $comments[] = $row; - $lineno++; } DBA::close($thread_items); - if (!empty($direction)) { - foreach ($parentlines as $line) { - $comments[$line]['direction'] = $direction; - if (!empty($actor)) { - $comments[$line]['reshared'] = DI::l10n()->t('%s reshared this.', $actor['url']); - if (DI::pConfig()->get(local_user(), 'system', 'display_resharer') ) { - $comments[$line]['owner-link'] = $actor['link']; - $comments[$line]['owner-avatar'] = $actor['avatar']; - $comments[$line]['owner-name'] = $actor['name']; - } - } - } - } return $comments; } diff --git a/src/Model/Item.php b/src/Model/Item.php index 2947fd36f4..a42e466460 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -80,6 +80,7 @@ class Item 'allow_cid', 'allow_gid', 'deny_cid', 'deny_gid', 'item_id', 'author-id', 'author-link', 'author-name', 'author-avatar', 'author-network', 'owner-id', 'owner-link', 'owner-name', 'owner-avatar', 'owner-network', + 'causer-id', 'causer-link', 'causer-name', 'causer-avatar', 'causer-contact-type', 'contact-id', 'contact-uid', 'contact-link', 'contact-name', 'contact-avatar', 'writable', 'self', 'cid', 'alias', 'pinned', 'event-id', 'event-created', 'event-edited', 'event-start', 'event-finish', @@ -117,7 +118,7 @@ class Item 'title', 'content-warning', 'body', 'location', 'coord', 'app', 'rendered-hash', 'rendered-html', 'object-type', 'object', 'target-type', 'target', 'author-id', 'author-link', 'author-name', 'author-avatar', 'author-network', - 'owner-id', 'owner-link', 'owner-name', 'owner-avatar']; + 'owner-id', 'owner-link', 'owner-name', 'owner-avatar', 'causer-id']; // List of all verbs that don't need additional content data. // Never reorder or remove entries from this list. Just add new ones at the end, if needed. @@ -653,7 +654,7 @@ class Item $fields = []; $fields['item'] = ['id', 'uid', 'parent', 'uri', 'parent-uri', 'thr-parent', - 'guid', 'uri-id', 'parent-uri-id', 'thr-parent-id', 'vid', + 'guid', 'uri-id', 'parent-uri-id', 'thr-parent-id', 'vid', 'causer-id', 'contact-id', 'owner-id', 'author-id', 'type', 'wall', 'gravity', 'extid', 'created', 'edited', 'commented', 'received', 'changed', 'psid', 'resource-id', 'event-id', 'attach', 'post-type', 'file', @@ -681,6 +682,10 @@ class Item $fields['owner'] = ['url' => 'owner-link', 'name' => 'owner-name', 'addr' => 'owner-addr', 'thumb' => 'owner-avatar', 'nick' => 'owner-nick', 'network' => 'owner-network']; + $fields['causer'] = ['url' => 'causer-link', 'name' => 'causer-name', 'addr' => 'causer-addr', + 'thumb' => 'causer-avatar', 'nick' => 'causer-nick', 'network' => 'causer-network', + 'contact-type' => 'causer-contact-type']; + $fields['contact'] = ['url' => 'contact-link', 'name' => 'contact-name', 'thumb' => 'contact-avatar', 'writable', 'self', 'id' => 'cid', 'alias', 'uid' => 'contact-uid', 'photo', 'name-date', 'uri-date', 'avatar-date', 'thumb', 'dfrn-id']; @@ -769,6 +774,9 @@ class Item $joins .= " LEFT JOIN `contact` AS `owner` ON `owner`.`id` = $master_table.`owner-id`"; } } + if (strpos($sql_commands, "`causer`.") !== false) { + $joins .= " LEFT JOIN `contact` AS `causer` ON `causer`.`id` = $master_table.`causer-id`"; + } if (strpos($sql_commands, "`group_member`.") !== false) { $joins .= " STRAIGHT_JOIN `group_member` ON `group_member`.`contact-id` = $master_table.`contact-id`"; @@ -1719,8 +1727,7 @@ class Item return 0; } - // We don't store the causer, we only have it here for the checks in the function above - unset($item['causer-id']); + // We don't store the causer link, only the id unset($item['causer-link']); // We don't store these fields anymore in the item table @@ -2030,11 +2037,12 @@ class Item } if ($author['contact-type'] != Contact::TYPE_COMMUNITY) { - if (!in_array($parent['post-type'], [self::PT_ARTICLE, self::PT_COMMENT]) || Contact::isSharing($parent['owner-id'], $item['uid'])) { + if (!in_array($parent['post-type'], [self::PT_ARTICLE, self::PT_COMMENT, self::PT_STORED, self::PT_GLOBAL, self::PT_RELAY, self::PT_FETCHED]) + || Contact::isSharing($parent['owner-id'], $item['uid'])) { Logger::info('The resharer is no forum: quit', ['resharer' => $item['author-id'], 'owner' => $parent['owner-id'], 'author' => $parent['author-id'], 'uid' => $item['uid']]); return; } - self::update(['post-type' => self::PT_ANNOUNCEMENT], ['id' => $parent['id']]); + self::update(['post-type' => self::PT_ANNOUNCEMENT, 'causer-id' => $item['author-id']], ['id' => $parent['id']]); Logger::info('Set announcement post-type', ['uri-id' => $item['uri-id'], 'thr-parent-id' => $item['thr-parent-id'], 'uid' => $item['uid']]); return; } diff --git a/src/Protocol/ActivityPub/Processor.php b/src/Protocol/ActivityPub/Processor.php index 037c7889cb..5d5bfc0b1c 100644 --- a/src/Protocol/ActivityPub/Processor.php +++ b/src/Protocol/ActivityPub/Processor.php @@ -529,6 +529,10 @@ class Processor } } + if (!empty($activity['from-relay'])) { + $item['causer-id'] = $activity['from-relay']; + } + if ($item['isForum'] ?? false) { $item['contact-id'] = Contact::getIdForURL($activity['actor'], $receiver); } else { @@ -696,13 +700,13 @@ class Processor /** * Fetches missing posts * - * @param string $url message URL - * @param array $child activity array with the child of this message - * @param string $actor Relay actor + * @param string $url message URL + * @param array $child activity array with the child of this message + * @param string $relay_actor Relay actor * @return string fetched message URL * @throws \Friendica\Network\HTTPException\InternalServerErrorException */ - public static function fetchMissingActivity(string $url, array $child = [], string $actor = '') + public static function fetchMissingActivity(string $url, array $child = [], string $relay_actor = '') { if (!empty($child['receiver'])) { $uid = ActivityPub\Receiver::getFirstUserFromReceivers($child['receiver']); @@ -761,7 +765,7 @@ class Processor $ldactivity = JsonLD::compact($activity); $ldactivity['thread-completion'] = true; - $ldactivity['from-relay'] = !empty($actor); + $ldactivity['from-relay'] = Contact::getIdForURL($relay_actor); ActivityPub\Receiver::processActivity($ldactivity, json_encode($activity), $uid, true, false, $signer); diff --git a/static/dbstructure.config.php b/static/dbstructure.config.php index ea506b4a92..2e53649b97 100755 --- a/static/dbstructure.config.php +++ b/static/dbstructure.config.php @@ -54,7 +54,7 @@ use Friendica\Database\DBA; if (!defined('DB_UPDATE_VERSION')) { - define('DB_UPDATE_VERSION', 1368); + define('DB_UPDATE_VERSION', 1369); } return [ @@ -722,6 +722,7 @@ return [ "network" => ["type" => "char(4)", "not null" => "1", "default" => "", "comment" => "Network from where the item comes from"], "owner-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "relation" => ["contact" => "id"], "comment" => "Link to the contact table with uid=0 of the owner of this item"], "author-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "relation" => ["contact" => "id"], "comment" => "Link to the contact table with uid=0 of the author of this item"], + "causer-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "relation" => ["contact" => "id"], "comment" => "Link to the contact table with uid=0 of the contact that caused the item creation"], "icid" => ["type" => "int unsigned", "relation" => ["item-content" => "id"], "comment" => "Id of the item-content table entry that contains the whole item content"], "iaid" => ["type" => "int unsigned", "relation" => ["item-activity" => "id"], "comment" => "Id of the item-activity table entry that contains the activity data"], "vid" => ["type" => "smallint unsigned", "relation" => ["verb" => "id"], "comment" => "Id of the verb table entry that contains the activity verbs"], From d3abf5eff92220b5791106cdfd16d2f25f8a462d Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 22 Sep 2020 05:57:03 +0000 Subject: [PATCH 2/3] Set "follower" on relayed posts as well --- src/Model/Item.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Model/Item.php b/src/Model/Item.php index a42e466460..970c5f4a56 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -1712,7 +1712,7 @@ class Item $item['owner-id'] = ($item['owner-id'] ?? 0) ?: Contact::getIdForURL($item['owner-link'], 0, null, $default); $actor = ($item['gravity'] == GRAVITY_PARENT) ? $item['owner-id'] : $item['author-id']; - if (!$item['origin'] && in_array($item['post-type'], [self::PT_ARTICLE, self::PT_COMMENT, self::PT_GLOBAL]) && Contact::isSharing($actor, $item['uid'])) { + if (!$item['origin'] && in_array($item['post-type'], [self::PT_ARTICLE, self::PT_COMMENT, self::PT_RELAY, self::PT_GLOBAL]) && Contact::isSharing($actor, $item['uid'])) { $item['post-type'] = self::PT_FOLLOWER; } From 93cd85595c8e761bf503c577a05239a500d347b6 Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 22 Sep 2020 07:19:44 +0000 Subject: [PATCH 3/3] Added foreign key --- database.sql | 2 ++ src/Model/Item.php | 2 +- src/Worker/MergeContact.php | 1 + static/dbstructure.config.php | 3 ++- 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/database.sql b/database.sql index 499ac3b033..f598ab9ccb 100644 --- a/database.sql +++ b/database.sql @@ -740,9 +740,11 @@ CREATE TABLE IF NOT EXISTS `item` ( INDEX `uri-id` (`uri-id`), INDEX `parent-uri-id` (`parent-uri-id`), INDEX `thr-parent-id` (`thr-parent-id`), + INDEX `causer-id` (`causer-id`), FOREIGN KEY (`uri-id`) REFERENCES `item-uri` (`id`) ON UPDATE RESTRICT ON DELETE CASCADE, FOREIGN KEY (`parent-uri-id`) REFERENCES `item-uri` (`id`) ON UPDATE RESTRICT ON DELETE CASCADE, FOREIGN KEY (`thr-parent-id`) REFERENCES `item-uri` (`id`) ON UPDATE RESTRICT ON DELETE CASCADE, + FOREIGN KEY (`causer-id`) REFERENCES `contact` (`id`) ON UPDATE RESTRICT ON DELETE RESTRICT, FOREIGN KEY (`psid`) REFERENCES `permissionset` (`id`) ON UPDATE RESTRICT ON DELETE RESTRICT ) DEFAULT COLLATE utf8mb4_general_ci COMMENT='Structure for all posts'; diff --git a/src/Model/Item.php b/src/Model/Item.php index 970c5f4a56..d03e9ec354 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -775,7 +775,7 @@ class Item } } if (strpos($sql_commands, "`causer`.") !== false) { - $joins .= " LEFT JOIN `contact` AS `causer` ON `causer`.`id` = $master_table.`causer-id`"; + $joins .= " LEFT JOIN `contact` AS `causer` ON `causer`.`id` = `item`.`causer-id`"; } if (strpos($sql_commands, "`group_member`.") !== false) { diff --git a/src/Worker/MergeContact.php b/src/Worker/MergeContact.php index 3bb4e7e689..e04dfb6ac8 100644 --- a/src/Worker/MergeContact.php +++ b/src/Worker/MergeContact.php @@ -55,6 +55,7 @@ class MergeContact DBA::delete('post-tag', ['cid' => $old_cid]); DBA::update('item', ['author-id' => $new_cid], ['author-id' => $old_cid]); DBA::update('item', ['owner-id' => $new_cid], ['owner-id' => $old_cid]); + DBA::update('item', ['causer-id' => $new_cid], ['causer-id' => $old_cid]); DBA::update('thread', ['author-id' => $new_cid], ['author-id' => $old_cid]); DBA::update('thread', ['owner-id' => $new_cid], ['owner-id' => $old_cid]); } else { diff --git a/static/dbstructure.config.php b/static/dbstructure.config.php index 2e53649b97..7e69ec034c 100755 --- a/static/dbstructure.config.php +++ b/static/dbstructure.config.php @@ -722,7 +722,7 @@ return [ "network" => ["type" => "char(4)", "not null" => "1", "default" => "", "comment" => "Network from where the item comes from"], "owner-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "relation" => ["contact" => "id"], "comment" => "Link to the contact table with uid=0 of the owner of this item"], "author-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "relation" => ["contact" => "id"], "comment" => "Link to the contact table with uid=0 of the author of this item"], - "causer-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "relation" => ["contact" => "id"], "comment" => "Link to the contact table with uid=0 of the contact that caused the item creation"], + "causer-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["contact" => "id", "on delete" => "restrict"], "comment" => "Link to the contact table with uid=0 of the contact that caused the item creation"], "icid" => ["type" => "int unsigned", "relation" => ["item-content" => "id"], "comment" => "Id of the item-content table entry that contains the whole item content"], "iaid" => ["type" => "int unsigned", "relation" => ["item-activity" => "id"], "comment" => "Id of the item-activity table entry that contains the activity data"], "vid" => ["type" => "smallint unsigned", "relation" => ["verb" => "id"], "comment" => "Id of the verb table entry that contains the activity verbs"], @@ -814,6 +814,7 @@ return [ "uri-id" => ["uri-id"], "parent-uri-id" => ["parent-uri-id"], "thr-parent-id" => ["thr-parent-id"], + "causer-id" => ["causer-id"], ] ], "item-activity" => [