2021-08-02 12:41:41 +08:00
# frozen_string_literal: true
class TopicQuery
module PrivateMessageLists
2022-08-10 13:25:39 +08:00
def list_private_messages ( user , & blk )
2023-03-13 08:09:38 +08:00
list = user_personal_private_messages ( user )
2021-08-02 12:41:41 +08:00
list = not_archived ( list , user )
2022-09-30 13:44:04 +08:00
list = have_posts_from_others ( list , user )
2021-10-04 11:55:35 +08:00
2022-09-30 13:44:04 +08:00
create_list ( :private_messages , { } , list , & blk )
end
2023-03-13 08:09:38 +08:00
def list_private_messages_direct_and_groups ( user , groups_messages_notification_level : nil , & blk )
list =
user_personal_and_groups_private_messages (
user ,
groups_messages_notification_level : groups_messages_notification_level ,
)
2022-09-30 13:44:04 +08:00
list = not_archived ( list , user )
list = not_archived_in_groups ( list )
list = have_posts_from_others ( list , user )
2021-10-04 11:55:35 +08:00
2022-08-10 13:25:39 +08:00
create_list ( :private_messages , { } , list , & blk )
2021-08-02 12:41:41 +08:00
end
def list_private_messages_archive ( user )
2023-03-13 08:09:38 +08:00
list = user_personal_private_messages ( user )
2021-08-02 12:41:41 +08:00
list =
list . joins ( :user_archived_messages ) . where ( " user_archived_messages.user_id = ? " , user . id )
2023-03-13 08:09:38 +08:00
2021-08-02 12:41:41 +08:00
create_list ( :private_messages , { } , list )
end
def list_private_messages_sent ( user )
2023-03-13 08:09:38 +08:00
list = user_personal_private_messages ( user )
2021-08-02 12:41:41 +08:00
list = list . where ( << ~ SQL , user . id )
EXISTS (
SELECT 1 FROM posts
WHERE posts . topic_id = topics . id AND posts . user_id = ?
)
SQL
list = not_archived ( list , user )
create_list ( :private_messages , { } , list )
end
def list_private_messages_new ( user , type = :user )
2021-07-30 17:00:48 +08:00
list = filter_private_message_new ( user , type )
2021-11-16 14:40:50 +08:00
list = TopicQuery . remove_muted_tags ( list , user )
2021-07-30 17:00:48 +08:00
list = remove_dismissed ( list , user )
2021-08-02 12:41:41 +08:00
create_list ( :private_messages , { } , list )
end
def list_private_messages_unread ( user , type = :user )
2021-07-30 17:00:48 +08:00
list = filter_private_messages_unread ( user , type )
2021-08-02 12:41:41 +08:00
create_list ( :private_messages , { } , list )
end
def list_private_messages_group ( user )
2023-03-13 08:09:38 +08:00
list = user_groups_private_messages ( user )
2021-08-02 12:41:41 +08:00
list = list . joins ( << ~ SQL )
LEFT JOIN group_archived_messages gm
ON gm . topic_id = topics . id AND gm . group_id = #{group.id.to_i}
SQL
list = list . where ( " gm.id IS NULL " )
publish_read_state = ! ! group . publish_read_state
list = append_read_state ( list , group ) if publish_read_state
2023-05-31 22:02:06 +08:00
create_list ( :private_messages , { publish_read_state : publish_read_state , group : group } , list )
2021-08-02 12:41:41 +08:00
end
def list_private_messages_group_archive ( user )
2023-03-13 08:09:38 +08:00
list = user_groups_private_messages ( user )
2021-08-02 12:41:41 +08:00
list = list . joins ( << ~ SQL )
INNER JOIN group_archived_messages gm
ON gm . topic_id = topics . id AND gm . group_id = #{group.id.to_i}
SQL
publish_read_state = ! ! group . publish_read_state
list = append_read_state ( list , group ) if publish_read_state
2023-05-31 22:02:06 +08:00
create_list ( :private_messages , { publish_read_state : publish_read_state , group : group } , list )
2021-08-02 12:41:41 +08:00
end
def list_private_messages_group_new ( user )
2021-07-30 17:00:48 +08:00
list = filter_private_message_new ( user , :group )
2021-08-05 16:36:52 +08:00
list = remove_dismissed ( list , user )
2021-08-02 12:41:41 +08:00
publish_read_state = ! ! group . publish_read_state
list = append_read_state ( list , group ) if publish_read_state
2023-05-31 22:02:06 +08:00
create_list ( :private_messages , { publish_read_state : publish_read_state , group : group } , list )
2021-08-02 12:41:41 +08:00
end
def list_private_messages_group_unread ( user )
2021-07-30 17:00:48 +08:00
list = filter_private_messages_unread ( user , :group )
2021-08-02 12:41:41 +08:00
publish_read_state = ! ! group . publish_read_state
list = append_read_state ( list , group ) if publish_read_state
2023-05-31 22:02:06 +08:00
create_list ( :private_messages , { publish_read_state : publish_read_state , group : group } , list )
2021-08-02 12:41:41 +08:00
end
def list_private_messages_warnings ( user )
2023-03-13 08:09:38 +08:00
list = user_personal_private_messages ( user )
2021-08-02 12:41:41 +08:00
list = list . where ( " topics.subtype = ? " , TopicSubtype . moderator_warning )
# Exclude official warnings that the user created, instead of received
list = list . where ( " topics.user_id <> ? " , user . id )
create_list ( :private_messages , { } , list )
end
def private_messages_for ( user , type )
if type == :group
2023-03-13 08:09:38 +08:00
user_groups_private_messages ( user )
2021-08-02 12:41:41 +08:00
elsif type == :user
2023-03-13 08:09:38 +08:00
user_personal_private_messages ( user )
2021-08-02 12:41:41 +08:00
elsif type == :all
2023-03-13 08:09:38 +08:00
user_personal_and_groups_private_messages ( user )
2021-08-02 12:41:41 +08:00
end
end
def list_private_messages_tag ( user )
2023-03-13 08:09:38 +08:00
list = user_personal_and_groups_private_messages ( user )
2021-08-02 12:41:41 +08:00
list =
list . joins (
" JOIN topic_tags tt ON tt.topic_id = topics.id
JOIN tags t ON t . id = tt . tag_id AND t . name = '#{@options[:tags][0]}' " ,
)
2023-03-13 08:09:38 +08:00
2021-08-02 12:41:41 +08:00
create_list ( :private_messages , { } , list )
end
2021-07-30 17:00:48 +08:00
def filter_private_messages_unread ( user , type )
list = TopicQuery . unread_filter ( private_messages_for ( user , type ) , whisperer : user . whisperer? )
2021-08-18 11:23:28 +08:00
first_unread_pm_at =
case type
when :user
user_first_unread_pm_at ( user )
when :group
2023-02-13 12:39:45 +08:00
GroupUser . where ( user : user , group : group ) . pick ( :first_unread_pm_at )
2021-08-18 11:23:28 +08:00
else
user_first_unread_pm_at = user_first_unread_pm_at ( user )
group_first_unread_pm_at = GroupUser . where ( user : user ) . minimum ( :first_unread_pm_at )
[ user_first_unread_pm_at , group_first_unread_pm_at ] . compact . min
end
2021-07-30 17:00:48 +08:00
list = list . where ( " topics.updated_at >= ? " , first_unread_pm_at ) if first_unread_pm_at
list
end
def filter_private_message_new ( user , type )
TopicQuery . new_filter (
private_messages_for ( user , type ) ,
treat_as_new_topic_start_date : user . user_option . treat_as_new_topic_start_date ,
)
end
2021-08-02 12:41:41 +08:00
private
def append_read_state ( list , group )
group_id = group . id
return list if group_id . nil?
selected_values = list . select_values . empty? ? [ " topics.* " ] : list . select_values
selected_values << " COALESCE(tg.last_read_post_number, 0) AS last_read_post_number "
list . joins (
" LEFT OUTER JOIN topic_groups tg ON topics.id = tg.topic_id AND tg.group_id = #{ group_id } " ,
) . select ( * selected_values )
end
def filter_archived ( list , user , archived : true )
2021-09-15 10:29:42 +08:00
# Executing an extra query instead of a sub-query because it is more
# efficient for the PG planner. Caution should be used when changing the
# query here as it can easily lead to an inefficient query.
group_ids = group_with_messages_ids ( user )
2021-09-15 11:32:10 +08:00
if group_ids . present?
list = list . joins ( << ~ SQL )
LEFT JOIN group_archived_messages gm
ON gm . topic_id = topics . id
AND gm . group_id IN ( #{group_ids.join(",")})
LEFT JOIN user_archived_messages um
ON um . user_id = #{user.id.to_i}
AND um . topic_id = topics . id
SQL
2021-08-02 12:41:41 +08:00
if archived
list . where ( " um.user_id IS NOT NULL OR gm.topic_id IS NOT NULL " )
else
list . where ( " um.user_id IS NULL AND gm.topic_id IS NULL " )
end
2021-09-15 11:32:10 +08:00
else
list = list . joins ( << ~ SQL )
LEFT JOIN user_archived_messages um
ON um . user_id = #{user.id.to_i}
AND um . topic_id = topics . id
SQL
2021-08-02 12:41:41 +08:00
2021-09-15 11:32:10 +08:00
list . where ( " um.user_id IS #{ archived ? " NOT NULL " : " NULL " } " )
end
2021-08-02 12:41:41 +08:00
end
def not_archived ( list , user )
list . joins (
" LEFT JOIN user_archived_messages um
ON um . user_id = #{user.id.to_i} AND um.topic_id = topics.id",
) . where ( " um.user_id IS NULL " )
end
2022-09-30 13:44:04 +08:00
def not_archived_in_groups ( list )
list . left_joins ( :group_archived_messages ) . where ( group_archived_messages : { id : nil } )
end
def have_posts_from_others ( list , user )
2022-11-02 03:05:13 +08:00
list . where ( << ~ SQL , user . id . to_i )
2022-09-30 13:44:04 +08:00
NOT (
topics . participant_count = 1
2022-11-02 03:05:13 +08:00
AND topics . user_id = ?
2022-09-30 13:44:04 +08:00
AND topics . moderator_posts_count = 0
)
SQL
end
2021-08-02 12:41:41 +08:00
def group
@group || =
begin
Group . where ( " name ilike ? " , @options [ :group_name ] ) . select ( :id , :publish_read_state ) . first
end
end
2021-08-18 11:23:28 +08:00
def user_first_unread_pm_at ( user )
2023-02-13 12:39:45 +08:00
UserStat . where ( user : user ) . pick ( :first_unread_pm_at )
2021-08-18 11:23:28 +08:00
end
2021-09-15 10:29:42 +08:00
def group_with_messages_ids ( user )
@group_with_messages_ids || = { }
if ids = @group_with_messages_ids [ user . id ]
return ids
end
@group_with_messages_ids [ user . id ] = user . groups . where ( has_messages : true ) . pluck ( :id )
end
2023-03-13 08:09:38 +08:00
private
def private_messages_default_scope ( user )
options = @options
options . reverse_merge! ( per_page : per_page_setting )
result =
Topic
. private_messages
. includes ( :allowed_users )
2023-05-31 22:02:06 +08:00
. includes ( :allowed_groups )
2023-03-13 08:09:38 +08:00
. joins (
" LEFT OUTER JOIN topic_users AS tu ON (topics.id = tu.topic_id AND tu.user_id = #{ user . id . to_i } ) " ,
)
. order ( " topics.bumped_at DESC " )
result = result . includes ( :tags ) if SiteSetting . tagging_enabled
result = result . limit ( options [ :per_page ] ) unless options [ :limit ] == false
result = result . visible if options [ :visible ] || @user . nil? || @user . regular?
if options [ :page ]
offset = options [ :page ] . to_i * options [ :per_page ]
result = result . offset ( offset ) if offset > 0
end
result
end
def user_groups_private_messages ( user )
result = private_messages_default_scope ( user )
result =
result . joins (
" INNER JOIN topic_allowed_groups tag ON tag.topic_id = topics.id AND tag.group_id IN (SELECT id FROM groups WHERE LOWER(name) = ' #{ PG :: Connection . escape_string ( @options [ :group_name ] . downcase ) } ') " ,
)
unless user . admin?
result =
result . joins (
" INNER JOIN group_users gu ON gu.group_id = tag.group_id AND gu.user_id = #{ user . id . to_i } " ,
)
end
result
end
def user_personal_private_messages ( user )
result = private_messages_default_scope ( user )
result . where (
" topics.id IN (SELECT topic_id FROM topic_allowed_users WHERE user_id = ?) " ,
user . id . to_i ,
)
end
def user_personal_and_groups_private_messages ( user , groups_messages_notification_level : nil )
result = private_messages_default_scope ( user )
group_ids = group_with_messages_ids ( user )
topic_allowed_groups_scope =
if groups_messages_notification_level . present? &&
notification_level =
NotificationLevels . topic_levels [ groups_messages_notification_level ]
<< ~ SQL
SELECT topic_allowed_groups . topic_id
FROM topic_allowed_groups
INNER JOIN topic_users ON topic_users . topic_id = topic_allowed_groups . topic_id AND topic_users . user_id = :user_id
WHERE group_id IN ( :group_ids )
AND topic_users . notification_level > = #{notification_level.to_i}
SQL
else
" SELECT topic_id FROM topic_allowed_groups WHERE group_id IN (:group_ids) "
end
result =
if group_ids . present?
result . where ( << ~ SQL , user_id : user . id . to_i , group_ids : group_ids )
topics . id IN (
SELECT topic_id
FROM topic_allowed_users
WHERE user_id = :user_id
UNION ALL
#{topic_allowed_groups_scope}
)
SQL
else
result . joins ( << ~ SQL )
INNER JOIN topic_allowed_users tau
ON tau . topic_id = topics . id
AND tau . user_id = #{user.id.to_i}
SQL
end
end
2021-08-02 12:41:41 +08:00
end
end