X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FModel%2FPost%2FUserNotification.php;h=dd0bbbe1ecf0249379cfe585cbe089311e7e0978;hb=5f6503a73fabbd65b9ddb1de430b73f472c53dfe;hp=806dfe26e5bdfa000a4bf0833aca1e6b1532198a;hpb=50580fd04cf7639905ff77dd8a58910c9c8c5a52;p=friendica.git diff --git a/src/Model/Post/UserNotification.php b/src/Model/Post/UserNotification.php index 806dfe26e5..dd0bbbe1ec 100644 --- a/src/Model/Post/UserNotification.php +++ b/src/Model/Post/UserNotification.php @@ -1,6 +1,6 @@ truncateFieldsForTable('post-user-notification', $data); $fields['uri-id'] = $uri_id; $fields['uid'] = $uid; @@ -91,7 +92,7 @@ class UserNotification throw new BadMethodCallException('Empty URI_id'); } - $fields = DBStructure::getFieldsForTable('post-user-notification', $data); + $fields = DI::dbaDefinition()->truncateFieldsForTable('post-user-notification', $data); // Remove the key fields unset($fields['uri-id']); @@ -132,12 +133,18 @@ class UserNotification public static function setNotification(int $uri_id, int $uid) { $fields = ['id', 'uri-id', 'parent-uri-id', 'uid', 'body', 'parent', 'gravity', 'vid', 'gravity', - 'private', 'contact-id', 'thr-parent', 'thr-parent-id', 'parent-uri-id', 'parent-uri', 'author-id', 'verb']; + 'contact-id', 'author-id', 'owner-id', 'causer-id', + 'private', 'thr-parent', 'thr-parent-id', 'parent-uri-id', 'parent-uri', 'verb']; $item = Post::selectFirst($fields, ['uri-id' => $uri_id, 'uid' => $uid, 'origin' => false]); if (!DBA::isResult($item)) { return; } + $parent = Post::selectFirstPost(['author-id', 'owner-id', 'causer-id'], ['uri-id' => $item['parent-uri-id']]); + if (!DBA::isResult($parent)) { + return; + } + // "Activity::FOLLOW" is an automated activity, so we ignore it here if ($item['verb'] == Activity::FOLLOW) { return; @@ -160,28 +167,43 @@ class UserNotification DBA::close($users); foreach (array_unique($uids) as $uid) { - self::setNotificationForUser($item, $uid); + self::setNotificationForUser($item, $parent, $uid); } } /** * Checks an item for notifications for the given user and sets the "notification-type" field * - * @param array $item Item array - * @param int $uid User ID + * @param array $item Item array + * @param array $parent Parent item array + * @param int $uid User ID * @throws HTTPException\InternalServerErrorException */ - private static function setNotificationForUser(array $item, int $uid) + private static function setNotificationForUser(array $item, array $parent, int $uid) { if (Post\ThreadUser::getIgnored($item['parent-uri-id'], $uid)) { return; } - $user = User::getById($uid, ['account-type']); + foreach (array_unique([$parent['author-id'], $parent['owner-id'], $parent['causer-id'], $item['author-id'], $item['owner-id'], $item['causer-id']]) as $author_id) { + if (empty($author_id)) { + continue; + } + if (Contact\User::isBlocked($author_id, $uid) || Contact\User::isIgnored($author_id, $uid) || Contact\User::isCollapsed($author_id, $uid)) { + Logger::debug('Author is blocked/ignored/collapsed by user', ['uid' => $uid, 'author' => $author_id, 'uri-id' => $item['uri-id']]); + return; + } + } + + $user = User::getById($uid, ['account-type', 'account_removed', 'account_expired']); if (in_array($user['account-type'], [User::ACCOUNT_TYPE_COMMUNITY, User::ACCOUNT_TYPE_RELAY])) { return; } + if ($user['account_removed'] || $user['account_expired']) { + return; + } + $author = Contact::getById($item['author-id'], ['contact-type']); if (empty($author)) { return; @@ -193,6 +215,8 @@ class UserNotification $notification_type = $notification_type | self::TYPE_SHARED; self::insertNotificationByItem(self::TYPE_SHARED, $uid, $item); $notified = true; + } elseif ($author['contact-type'] == Contact::TYPE_COMMUNITY) { + return; } else { $notified = false; } @@ -218,7 +242,7 @@ class UserNotification return; } - if (self::checkExplicitMention($item, $profiles)) { + if (($item['verb'] != Activity::ANNOUNCE) && self::checkExplicitMention($item, $profiles)) { $notification_type = $notification_type | self::TYPE_EXPLICIT_TAGGED; if (!$notified) { self::insertNotificationByItem(self::TYPE_EXPLICIT_TAGGED, $uid, $item); @@ -226,7 +250,7 @@ class UserNotification } } - if (self::checkImplicitMention($item, $profiles)) { + if (($item['verb'] != Activity::ANNOUNCE) && self::checkImplicitMention($item, $profiles)) { $notification_type = $notification_type | self::TYPE_IMPLICIT_TAGGED; if (!$notified) { self::insertNotificationByItem(self::TYPE_IMPLICIT_TAGGED, $uid, $item); @@ -250,7 +274,7 @@ class UserNotification } } - if (self::checkCommentedThread($item, $contacts)) { + if (($item['verb'] != Activity::ANNOUNCE) && self::checkCommentedThread($item, $contacts)) { $notification_type = $notification_type | self::TYPE_THREAD_COMMENT; if (!$notified) { self::insertNotificationByItem(self::TYPE_THREAD_COMMENT, $uid, $item); @@ -258,7 +282,7 @@ class UserNotification } } - if (self::checkCommentedParticipation($item, $contacts)) { + if (($item['verb'] != Activity::ANNOUNCE) && self::checkCommentedParticipation($item, $contacts)) { $notification_type = $notification_type | self::TYPE_COMMENT_PARTICIPATION; if (!$notified) { self::insertNotificationByItem(self::TYPE_COMMENT_PARTICIPATION, $uid, $item); @@ -266,7 +290,23 @@ class UserNotification } } - if (self::checkActivityParticipation($item, $contacts)) { + if (($item['verb'] != Activity::ANNOUNCE) && self::checkQuoted($item, $contacts)) { + $notification_type = $notification_type | self::TYPE_QUOTED; + if (!$notified) { + self::insertNotificationByItem(self::TYPE_QUOTED, $uid, $item); + $notified = true; + } + } + + if (($item['verb'] != Activity::ANNOUNCE) && self::checkFollowParticipation($item, $contacts)) { + $notification_type = $notification_type | self::TYPE_FOLLOW; + if (!$notified) { + self::insertNotificationByItem(self::TYPE_FOLLOW, $uid, $item); + $notified = true; + } + } + + if (($item['verb'] != Activity::ANNOUNCE) && self::checkActivityParticipation($item, $contacts)) { $notification_type = $notification_type | self::TYPE_ACTIVITY_PARTICIPATION; if (!$notified) { self::insertNotificationByItem(self::TYPE_ACTIVITY_PARTICIPATION, $uid, $item); @@ -278,7 +318,7 @@ class UserNotification } // Only create notifications for posts and comments, not for activities - if (($item['gravity'] == GRAVITY_ACTIVITY) && ($item['verb'] != Activity::ANNOUNCE)) { + if (($item['gravity'] == Item::GRAVITY_ACTIVITY) && ($item['verb'] != Activity::ANNOUNCE)) { return; } @@ -300,18 +340,18 @@ class UserNotification */ private static function insertNotificationByItem(int $type, int $uid, array $item): void { - if (($item['verb'] != Activity::ANNOUNCE) && ($item['gravity'] == GRAVITY_ACTIVITY) && + if (($item['verb'] != Activity::ANNOUNCE) && ($item['gravity'] == Item::GRAVITY_ACTIVITY) && !in_array($type, [self::TYPE_DIRECT_COMMENT, self::TYPE_DIRECT_THREAD_COMMENT])) { // Activities are only stored when performed on the user's post or comment return; } - $notification = (new Notifications\Factory\Notification(DI::logger()))->createForUser( + $notification = DI::notificationFactory()->createForUser( $uid, $item['vid'], $type, $item['author-id'], - $item['gravity'] == GRAVITY_ACTIVITY ? $item['thr-parent-id'] : $item['uri-id'], + $item['gravity'] == Item::GRAVITY_ACTIVITY ? $item['thr-parent-id'] : $item['uri-id'], $item['parent-uri-id'] ); @@ -326,7 +366,7 @@ class UserNotification /** * Add a notification entry * - * @param int $actor Contact ID of the actor + * @param int $actor Public contact ID of the actor * @param string $verb One of the Activity verb constant values * @param int $uid User ID * @return boolean @@ -334,7 +374,7 @@ class UserNotification */ public static function insertNotification(int $actor, string $verb, int $uid): bool { - $notification = (new Notifications\Factory\Notification(DI::logger()))->createForRelationship( + $notification = DI::notificationFactory()->createForRelationship( $uid, $actor, $verb @@ -413,7 +453,21 @@ class UserNotification private static function checkShared(array $item, int $uid): bool { // Only check on original posts and reshare ("announce") activities, otherwise return - if (($item['gravity'] != GRAVITY_PARENT) && ($item['verb'] != Activity::ANNOUNCE)) { + if (($item['gravity'] != Item::GRAVITY_PARENT) && ($item['verb'] != Activity::ANNOUNCE)) { + return false; + } + + // Don't notify about reshares by communities of our own posts or each time someone comments + if (($item['verb'] == Activity::ANNOUNCE) && DBA::exists('contact', ['id' => $item['contact-id'], 'contact-type' => Contact::TYPE_COMMUNITY])) { + $post = Post::selectFirst(['origin', 'gravity'], ['uri-id' => $item['thr-parent-id'], 'uid' => $uid]); + if (!$post || $post['origin'] || ($post['gravity'] != Item::GRAVITY_PARENT)) { + return false; + } + } + + // Only check on posts by the user itself + $cdata = Contact::getPublicAndUserContactID($item['contact-id'], $item['uid']); + if (empty($cdata['user']) || ($item['author-id'] != $cdata['public'])) { return false; } @@ -479,7 +533,7 @@ class UserNotification */ private static function checkCommentedThread(array $item, array $contacts): bool { - $condition = ['parent' => $item['parent'], 'author-id' => $contacts, 'deleted' => false, 'gravity' => GRAVITY_PARENT]; + $condition = ['parent' => $item['parent'], 'author-id' => $contacts, 'deleted' => false, 'gravity' => Item::GRAVITY_PARENT]; return Post::exists($condition); } @@ -493,7 +547,7 @@ class UserNotification */ private static function checkDirectComment(array $item, array $contacts): bool { - $condition = ['uri' => $item['thr-parent'], 'uid' => $item['uid'], 'author-id' => $contacts, 'deleted' => false, 'gravity' => GRAVITY_COMMENT]; + $condition = ['uri' => $item['thr-parent'], 'uid' => $item['uid'], 'author-id' => $contacts, 'deleted' => false, 'gravity' => Item::GRAVITY_COMMENT]; return Post::exists($condition); } @@ -507,7 +561,7 @@ class UserNotification */ private static function checkDirectCommentedThread(array $item, array $contacts): bool { - $condition = ['uri' => $item['thr-parent'], 'uid' => $item['uid'], 'author-id' => $contacts, 'deleted' => false, 'gravity' => GRAVITY_PARENT]; + $condition = ['uri' => $item['thr-parent'], 'uid' => $item['uid'], 'author-id' => $contacts, 'deleted' => false, 'gravity' => Item::GRAVITY_PARENT]; return Post::exists($condition); } @@ -521,7 +575,21 @@ class UserNotification */ private static function checkCommentedParticipation(array $item, array $contacts): bool { - $condition = ['parent' => $item['parent'], 'author-id' => $contacts, 'deleted' => false, 'gravity' => GRAVITY_COMMENT]; + $condition = ['parent' => $item['parent'], 'author-id' => $contacts, 'deleted' => false, 'gravity' => Item::GRAVITY_COMMENT]; + return Post::exists($condition); + } + + /** + * Check if the user follows this thread + * + * @param array $item + * @param array $contacts Array of contact IDs + * @return bool The user follows the thread + * @throws Exception + */ + private static function checkFollowParticipation(array $item, array $contacts): bool + { + $condition = ['parent' => $item['parent'], 'author-id' => $contacts, 'deleted' => false, 'gravity' => Item::GRAVITY_ACTIVITY, 'verb' => Activity::FOLLOW]; return Post::exists($condition); } @@ -535,7 +603,26 @@ class UserNotification */ private static function checkActivityParticipation(array $item, array $contacts): bool { - $condition = ['parent' => $item['parent'], 'author-id' => $contacts, 'deleted' => false, 'gravity' => GRAVITY_ACTIVITY]; + $condition = ['parent' => $item['parent'], 'author-id' => $contacts, 'deleted' => false, 'gravity' => Item::GRAVITY_ACTIVITY]; return Post::exists($condition); } + + /** + * Check for a quoted post of a post of the given user + * + * @param array $item + * @param array $contacts Array of contact IDs + * @return bool The item is a quoted post of a user's post or comment + * @throws Exception + */ + private static function checkQuoted(array $item, array $contacts): bool + { + if (empty($item['quote-uri-id'])) { + return false; + } + $condition = ['uri-id' => $item['quote-uri-id'], 'uid' => $item['uid'], 'author-id' => $contacts, 'deleted' => false, 'gravity' => [item::GRAVITY_PARENT, Item::GRAVITY_COMMENT]]; + return Post::exists($condition); + } + + }