2021-08-02 00:41:41 -04:00
# frozen_string_literal: true
class TopicQuery
module PrivateMessageLists
2022-08-10 01:25:39 -04:00
def list_private_messages ( user , & blk )
2021-08-02 00:41:41 -04:00
list = private_messages_for ( user , :user )
list = not_archived ( list , user )
2022-09-30 01:44:04 -04:00
list = have_posts_from_others ( list , user )
2021-10-03 23:55:35 -04:00
2022-09-30 01:44:04 -04:00
create_list ( :private_messages , { } , list , & blk )
end
def list_private_messages_direct_and_groups ( user , & blk )
list = private_messages_for ( user , :all )
list = not_archived ( list , user )
list = not_archived_in_groups ( list )
list = have_posts_from_others ( list , user )
2021-10-03 23:55:35 -04:00
2022-08-10 01:25:39 -04:00
create_list ( :private_messages , { } , list , & blk )
2021-08-02 00:41:41 -04:00
end
def list_private_messages_archive ( user )
list = private_messages_for ( user , :user )
list =
list . joins ( :user_archived_messages ) . where ( " user_archived_messages.user_id = ? " , user . id )
create_list ( :private_messages , { } , list )
end
def list_private_messages_sent ( user )
list = private_messages_for ( user , :user )
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 05:00:48 -04:00
list = filter_private_message_new ( user , type )
2021-11-16 01:40:50 -05:00
list = TopicQuery . remove_muted_tags ( list , user )
2021-07-30 05:00:48 -04:00
list = remove_dismissed ( list , user )
2021-08-02 00:41:41 -04:00
create_list ( :private_messages , { } , list )
end
def list_private_messages_unread ( user , type = :user )
2021-07-30 05:00:48 -04:00
list = filter_private_messages_unread ( user , type )
2021-08-02 00:41:41 -04:00
create_list ( :private_messages , { } , list )
end
def list_private_messages_group ( user )
list = private_messages_for ( user , :group )
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
create_list ( :private_messages , { publish_read_state : publish_read_state } , list )
end
def list_private_messages_group_archive ( user )
list = private_messages_for ( user , :group )
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
create_list ( :private_messages , { publish_read_state : publish_read_state } , list )
end
def list_private_messages_group_new ( user )
2021-07-30 05:00:48 -04:00
list = filter_private_message_new ( user , :group )
2021-08-05 04:36:52 -04:00
list = remove_dismissed ( list , user )
2021-08-02 00:41:41 -04:00
publish_read_state = ! ! group . publish_read_state
list = append_read_state ( list , group ) if publish_read_state
create_list ( :private_messages , { publish_read_state : publish_read_state } , list )
end
def list_private_messages_group_unread ( user )
2021-07-30 05:00:48 -04:00
list = filter_private_messages_unread ( user , :group )
2021-08-02 00:41:41 -04:00
publish_read_state = ! ! group . publish_read_state
list = append_read_state ( list , group ) if publish_read_state
create_list ( :private_messages , { publish_read_state : publish_read_state } , list )
end
def list_private_messages_warnings ( user )
list = private_messages_for ( user , :user )
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 )
options = @options
options . reverse_merge! ( per_page : per_page_setting )
result = Topic . includes ( :allowed_users )
result = result . includes ( :tags ) if SiteSetting . tagging_enabled
if type == :group
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
elsif type == :user
2022-11-01 15:05:13 -04:00
result =
result . where (
" topics.id IN (SELECT topic_id FROM topic_allowed_users WHERE user_id = ?) " ,
user . id . to_i ,
)
2021-08-02 00:41:41 -04:00
elsif type == :all
2021-09-14 22:29:42 -04:00
group_ids = group_with_messages_ids ( user )
2021-09-14 23:32:10 -04:00
result =
if group_ids . present?
2022-11-01 15:05:13 -04:00
result . where ( << ~ SQL , user . id . to_i , group_ids )
2021-09-14 23:32:10 -04:00
topics . id IN (
SELECT topic_id
FROM topic_allowed_users
2022-11-01 15:05:13 -04:00
WHERE user_id = ?
2021-09-14 23:32:10 -04:00
UNION ALL
SELECT topic_id FROM topic_allowed_groups
2022-11-01 15:05:13 -04:00
WHERE group_id IN ( ?)
2021-09-14 23:32:10 -04:00
)
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
2021-08-02 00:41:41 -04:00
end
result =
result
. 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 " )
. private_messages
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 list_private_messages_tag ( user )
list = private_messages_for ( user , :all )
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]}' " ,
)
create_list ( :private_messages , { } , list )
end
2021-07-30 05:00:48 -04:00
def filter_private_messages_unread ( user , type )
list = TopicQuery . unread_filter ( private_messages_for ( user , type ) , whisperer : user . whisperer? )
2021-08-17 23:23:28 -04:00
first_unread_pm_at =
case type
when :user
user_first_unread_pm_at ( user )
when :group
2023-02-12 23:39:45 -05:00
GroupUser . where ( user : user , group : group ) . pick ( :first_unread_pm_at )
2021-08-17 23:23:28 -04: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 05:00:48 -04: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 00:41:41 -04: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-14 22:29:42 -04: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-14 23:32:10 -04: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 00:41:41 -04: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-14 23:32:10 -04: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 00:41:41 -04:00
2021-09-14 23:32:10 -04:00
list . where ( " um.user_id IS #{ archived ? " NOT NULL " : " NULL " } " )
end
2021-08-02 00:41:41 -04: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 01:44:04 -04: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-01 15:05:13 -04:00
list . where ( << ~ SQL , user . id . to_i )
2022-09-30 01:44:04 -04:00
NOT (
topics . participant_count = 1
2022-11-01 15:05:13 -04:00
AND topics . user_id = ?
2022-09-30 01:44:04 -04:00
AND topics . moderator_posts_count = 0
)
SQL
end
2021-08-02 00:41:41 -04:00
def group
@group || =
begin
Group . where ( " name ilike ? " , @options [ :group_name ] ) . select ( :id , :publish_read_state ) . first
end
end
2021-08-17 23:23:28 -04:00
def user_first_unread_pm_at ( user )
2023-02-12 23:39:45 -05:00
UserStat . where ( user : user ) . pick ( :first_unread_pm_at )
2021-08-17 23:23:28 -04:00
end
2021-09-14 22:29:42 -04: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
2021-08-02 00:41:41 -04:00
end
end