Class: TopicView
- Inherits:
-
Object
- Object
- TopicView
- Defined in:
- lib/topic_view.rb
Constant Summary collapse
- MEGA_TOPIC_POSTS_COUNT =
10_000
- MIN_POST_READ_TIME =
4.0
- MAX_PARTICIPANTS =
24
- MAX_POSTS_COUNT_PARTICIPANTS =
if a topic has more that N posts no longer attempt to get accurate participant count, instead grab cached count from topic
500
Instance Attribute Summary collapse
-
#can_review_topic ⇒ Object
readonly
Returns the value of attribute can_review_topic.
-
#chunk_size ⇒ Object
readonly
Returns the value of attribute chunk_size.
-
#draft ⇒ Object
Returns the value of attribute draft.
-
#draft_key ⇒ Object
Returns the value of attribute draft_key.
-
#draft_sequence ⇒ Object
Returns the value of attribute draft_sequence.
-
#filtered_posts ⇒ Object
readonly
Returns the value of attribute filtered_posts.
-
#guardian ⇒ Object
readonly
Returns the value of attribute guardian.
-
#message_bus_last_id ⇒ Object
readonly
Returns the value of attribute message_bus_last_id.
-
#personal_message ⇒ Object
readonly
Returns the value of attribute personal_message.
-
#post_custom_fields ⇒ Object
Returns the value of attribute post_custom_fields.
-
#posts ⇒ Object
readonly
Returns the value of attribute posts.
-
#print ⇒ Object
readonly
Returns the value of attribute print.
-
#queued_posts_enabled ⇒ Object
(also: #queued_posts_enabled?)
readonly
Returns the value of attribute queued_posts_enabled.
-
#topic ⇒ Object
readonly
Returns the value of attribute topic.
-
#user_custom_fields ⇒ Object
Returns the value of attribute user_custom_fields.
Class Method Summary collapse
- .add_custom_filter(key, &blk) ⇒ Object
- .add_post_custom_fields_allowlister(&block) ⇒ Object
- .allowed_post_custom_fields(user, topic) ⇒ Object
-
.apply_custom_default_scope(&block) ⇒ Object
Configure a default scope to be applied to @filtered_posts.
- .cancel_preload(&blk) ⇒ Object
- .chunk_size ⇒ Object
- .custom_default_scopes ⇒ Object
- .custom_filters ⇒ Object
- .default_post_custom_fields ⇒ Object
- .on_preload(&blk) ⇒ Object
- .post_custom_fields_allowlisters ⇒ Object
- .preload(topic_view) ⇒ Object
- .print_chunk_size ⇒ Object
-
.reset_custom_default_scopes ⇒ Object
For testing.
Instance Method Summary collapse
- #absolute_url ⇒ Object
- #actions_summary ⇒ Object
- #all_post_actions ⇒ Object
- #bookmarks ⇒ Object
- #canonical_path ⇒ Object
- #category_group_moderator_user_ids ⇒ Object
- #contains_gaps? ⇒ Boolean
- #current_post_number ⇒ Object
- #desired_post ⇒ Object
- #filter_best(max, opts = {}) ⇒ Object
- #filter_posts(opts = {}) ⇒ Object
-
#filter_posts_near(post_number) ⇒ Object
Filter to all posts near a particular post number.
- #filter_posts_paged(page) ⇒ Object
- #filtered_post_id(post_number) ⇒ Object
- #filtered_post_ids ⇒ Object
-
#filtered_post_stream ⇒ Object
Returns an array of [id, days_ago] tuples.
- #gaps ⇒ Object
- #group_allowed_user_ids ⇒ Object
- #has_bookmarks? ⇒ Boolean
- #has_deleted? ⇒ Boolean
-
#highest_post_number ⇒ Object
This is pending a larger refactor, that allows custom orders for now we need to look for the highest_post_number in the stream the cache on topics is not correct if there are deleted posts at the end of the stream (for mods), nor is it correct for filtered streams.
- #image_url ⇒ Object
-
#initialize(topic_or_topic_id, user = nil, options = {}) ⇒ TopicView
constructor
A new instance of TopicView.
- #is_mega_topic? ⇒ Boolean
- #last_post ⇒ Object
- #last_post_id ⇒ Object
- #like_count ⇒ Object
- #link_counts ⇒ Object
- #links ⇒ Object
- #mentioned_users ⇒ Object
- #next_page ⇒ Object
- #next_page_path ⇒ Object
- #page_title ⇒ Object
- #participant_count ⇒ Object
- #participants ⇒ Object
- #pending_posts ⇒ Object
- #pm_params ⇒ Object
- #post_counts_by_user ⇒ Object
- #prev_page ⇒ Object
- #prev_page_path ⇒ Object
- #primary_group_names ⇒ Object
- #published_page ⇒ Object
- #published_time ⇒ Object
- #queued_posts_count ⇒ Object
- #read?(post_number) ⇒ Boolean
- #read_time ⇒ Object
- #recent_posts ⇒ Object
- #related_messages ⇒ Object
- #relative_url ⇒ Object
- #reviewable_counts ⇒ Object
- #show_read_indicator? ⇒ Boolean
- #suggested_topics ⇒ Object
- #summarizable? ⇒ Boolean
- #summary(opts = {}) ⇒ Object
- #title ⇒ Object
- #topic_allowed_group_ids ⇒ Object
- #topic_user ⇒ Object
- #unfiltered_post_ids ⇒ Object
Constructor Details
#initialize(topic_or_topic_id, user = nil, options = {}) ⇒ TopicView
Returns a new instance of TopicView.
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
# File 'lib/topic_view.rb', line 103 def initialize(topic_or_topic_id, user = nil, = {}) @topic = find_topic(topic_or_topic_id) @user = user @guardian = Guardian.new(@user) check_and_raise_exceptions([:skip_staff_action]) @message_bus_last_id = MessageBus.last_id("/topic/#{@topic.id}") .each { |key, value| self.instance_variable_set("@#{key}".to_sym, value) } @post_number = [@post_number.to_i, 1].max @include_suggested = .fetch(:include_suggested) { true } @include_related = .fetch(:include_related) { true } @chunk_size = case when @print TopicView.print_chunk_size else TopicView.chunk_size end @limit ||= @chunk_size @page = @page.to_i > 1 ? @page.to_i : calculate_page setup_filtered_posts @filtered_posts = apply_default_scope(@filtered_posts) filter_posts() if @posts && !@skip_custom_fields if (added_fields = User.allowed_user_custom_fields(@guardian)).present? @user_custom_fields = User.custom_fields_for_ids(@posts.map(&:user_id), added_fields) end if (allowed_fields = TopicView.allowed_post_custom_fields(@user, @topic)).present? @post_custom_fields = Post.custom_fields_for_ids(@posts.map(&:id), allowed_fields) end end TopicView.preload(self) @draft_key = @topic.draft_key @draft_sequence = DraftSequence.current(@user, @draft_key) @can_review_topic = @guardian.can_review_topic?(@topic) @queued_posts_enabled = NewPostManager.queue_enabled? || category_require_reply_approval? @personal_message = @topic. end |
Instance Attribute Details
#can_review_topic ⇒ Object (readonly)
Returns the value of attribute can_review_topic.
22 23 24 |
# File 'lib/topic_view.rb', line 22 def can_review_topic @can_review_topic end |
#chunk_size ⇒ Object (readonly)
Returns the value of attribute chunk_size.
22 23 24 |
# File 'lib/topic_view.rb', line 22 def chunk_size @chunk_size end |
#draft ⇒ Object
Returns the value of attribute draft.
37 38 39 |
# File 'lib/topic_view.rb', line 37 def draft @draft end |
#draft_key ⇒ Object
Returns the value of attribute draft_key.
37 38 39 |
# File 'lib/topic_view.rb', line 37 def draft_key @draft_key end |
#draft_sequence ⇒ Object
Returns the value of attribute draft_sequence.
37 38 39 |
# File 'lib/topic_view.rb', line 37 def draft_sequence @draft_sequence end |
#filtered_posts ⇒ Object (readonly)
Returns the value of attribute filtered_posts.
22 23 24 |
# File 'lib/topic_view.rb', line 22 def filtered_posts @filtered_posts end |
#guardian ⇒ Object (readonly)
Returns the value of attribute guardian.
22 23 24 |
# File 'lib/topic_view.rb', line 22 def guardian @guardian end |
#message_bus_last_id ⇒ Object (readonly)
Returns the value of attribute message_bus_last_id.
22 23 24 |
# File 'lib/topic_view.rb', line 22 def @message_bus_last_id end |
#personal_message ⇒ Object (readonly)
Returns the value of attribute personal_message.
22 23 24 |
# File 'lib/topic_view.rb', line 22 def @personal_message end |
#post_custom_fields ⇒ Object
Returns the value of attribute post_custom_fields.
37 38 39 |
# File 'lib/topic_view.rb', line 37 def post_custom_fields @post_custom_fields end |
#posts ⇒ Object (readonly)
Returns the value of attribute posts.
22 23 24 |
# File 'lib/topic_view.rb', line 22 def posts @posts end |
#print ⇒ Object (readonly)
Returns the value of attribute print.
22 23 24 |
# File 'lib/topic_view.rb', line 22 def print @print end |
#queued_posts_enabled ⇒ Object (readonly) Also known as: queued_posts_enabled?
Returns the value of attribute queued_posts_enabled.
22 23 24 |
# File 'lib/topic_view.rb', line 22 def queued_posts_enabled @queued_posts_enabled end |
#topic ⇒ Object (readonly)
Returns the value of attribute topic.
22 23 24 |
# File 'lib/topic_view.rb', line 22 def topic @topic end |
#user_custom_fields ⇒ Object
Returns the value of attribute user_custom_fields.
37 38 39 |
# File 'lib/topic_view.rb', line 37 def user_custom_fields @user_custom_fields end |
Class Method Details
.add_custom_filter(key, &blk) ⇒ Object
75 76 77 78 |
# File 'lib/topic_view.rb', line 75 def self.add_custom_filter(key, &blk) @custom_filters ||= {} @custom_filters[key] = blk end |
.add_post_custom_fields_allowlister(&block) ⇒ Object
65 66 67 |
# File 'lib/topic_view.rb', line 65 def self.add_post_custom_fields_allowlister(&block) post_custom_fields_allowlisters << block end |
.allowed_post_custom_fields(user, topic) ⇒ Object
69 70 71 72 73 |
# File 'lib/topic_view.rb', line 69 def self.allowed_post_custom_fields(user, topic) wpcf = default_post_custom_fields + post_custom_fields_allowlisters.map { |w| w.call(user, topic) } wpcf.flatten.uniq end |
.apply_custom_default_scope(&block) ⇒ Object
Configure a default scope to be applied to @filtered_posts. The registered block is called with @filtered_posts and an instance of ‘TopicView`.
This API should be considered experimental until it is exposed in ‘Plugin::Instance`.
90 91 92 |
# File 'lib/topic_view.rb', line 90 def self.apply_custom_default_scope(&block) custom_default_scopes << block end |
.cancel_preload(&blk) ⇒ Object
11 12 13 14 15 16 |
# File 'lib/topic_view.rb', line 11 def self.cancel_preload(&blk) if @preload @preload.delete blk @preload = nil if @preload.length == 0 end end |
.chunk_size ⇒ Object
53 54 55 |
# File 'lib/topic_view.rb', line 53 def self.chunk_size 20 end |
.custom_default_scopes ⇒ Object
94 95 96 |
# File 'lib/topic_view.rb', line 94 def self.custom_default_scopes @custom_default_scopes ||= [] end |
.custom_filters ⇒ Object
80 81 82 |
# File 'lib/topic_view.rb', line 80 def self.custom_filters @custom_filters || {} end |
.default_post_custom_fields ⇒ Object
57 58 59 |
# File 'lib/topic_view.rb', line 57 def self.default_post_custom_fields @default_post_custom_fields ||= [Post::NOTICE, "action_code_who", "action_code_path"] end |
.on_preload(&blk) ⇒ Object
7 8 9 |
# File 'lib/topic_view.rb', line 7 def self.on_preload(&blk) (@preload ||= Set.new) << blk end |
.post_custom_fields_allowlisters ⇒ Object
61 62 63 |
# File 'lib/topic_view.rb', line 61 def self.post_custom_fields_allowlisters @post_custom_fields_allowlisters ||= Set.new end |
.preload(topic_view) ⇒ Object
18 19 20 |
# File 'lib/topic_view.rb', line 18 def self.preload(topic_view) @preload.each { |preload| preload.call(topic_view) } if @preload end |
.print_chunk_size ⇒ Object
49 50 51 |
# File 'lib/topic_view.rb', line 49 def self.print_chunk_size 1000 end |
.reset_custom_default_scopes ⇒ Object
For testing
99 100 101 |
# File 'lib/topic_view.rb', line 99 def self.reset_custom_default_scopes @custom_default_scopes = nil end |
Instance Method Details
#absolute_url ⇒ Object
218 219 220 |
# File 'lib/topic_view.rb', line 218 def absolute_url "#{Discourse.base_url_no_prefix}#{relative_url}" end |
#actions_summary ⇒ Object
581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 |
# File 'lib/topic_view.rb', line 581 def actions_summary return @actions_summary unless @actions_summary.nil? @actions_summary = [] return @actions_summary unless post = posts&.first PostActionType.topic_flag_types.each do |sym, id| @actions_summary << { id: id, count: 0, hidden: false, can_act: @guardian.post_can_act?(post, sym), } end @actions_summary end |
#all_post_actions ⇒ Object
531 532 533 |
# File 'lib/topic_view.rb', line 531 def all_post_actions @all_post_actions ||= PostAction.counts_for(@posts, @user) end |
#bookmarks ⇒ Object
412 413 414 415 416 417 418 419 420 421 422 423 424 425 |
# File 'lib/topic_view.rb', line 412 def bookmarks return [] if @user.blank? return [] if @topic.trashed? @bookmarks ||= Bookmark.for_user_in_topic(@user, @topic.id).select( :id, :bookmarkable_id, :bookmarkable_type, :reminder_at, :name, :auto_delete_preference, ) end |
#canonical_path ⇒ Object
161 162 163 164 165 166 167 168 169 |
# File 'lib/topic_view.rb', line 161 def canonical_path if SiteSetting. = topic. return . if end path = relative_url.dup path << ((@page > 1) ? "?page=#{@page}" : "") path end |
#category_group_moderator_user_ids ⇒ Object
511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 |
# File 'lib/topic_view.rb', line 511 def category_group_moderator_user_ids @category_group_moderator_user_ids ||= begin if SiteSetting.enable_category_group_moderation? && @topic.category&.reviewable_by_group.present? posts_user_ids = Set.new(@posts.map(&:user_id)) Set.new( @topic .category .reviewable_by_group .group_users .where(user_id: posts_user_ids) .pluck("distinct user_id"), ) else Set.new end end end |
#contains_gaps? ⇒ Boolean
171 172 173 |
# File 'lib/topic_view.rb', line 171 def contains_gaps? @contains_gaps end |
#current_post_number ⇒ Object
694 695 696 697 698 |
# File 'lib/topic_view.rb', line 694 def current_post_number if highest_post_number.present? post_number > highest_post_number ? highest_post_number : post_number end end |
#desired_post ⇒ Object
259 260 261 262 263 264 265 266 |
# File 'lib/topic_view.rb', line 259 def desired_post return @desired_post if @desired_post.present? return nil if posts.blank? @desired_post = posts.detect { |p| p.post_number == @post_number } @desired_post ||= posts.first @desired_post end |
#filter_best(max, opts = {}) ⇒ Object
381 382 383 384 385 |
# File 'lib/topic_view.rb', line 381 def filter_best(max, opts = {}) filter = FilterBestPosts.new(@topic, @filtered_posts, max, opts) @posts = filter.posts @filtered_posts = filter.filtered_posts end |
#filter_posts(opts = {}) ⇒ Object
305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 |
# File 'lib/topic_view.rb', line 305 def filter_posts(opts = {}) if opts[:post_number].present? filter_posts_near(opts[:post_number].to_i) elsif opts[:post_ids].present? filter_posts_by_ids(opts[:post_ids]) elsif opts[:filter_post_number].present? # Only used for megatopics where we do not load the entire post stream filter_posts_by_post_number(opts[:filter_post_number], opts[:asc]) elsif opts[:best].present? # Only used for wordpress filter_best(opts[:best], opts) else filter_posts_paged(@page) end end |
#filter_posts_near(post_number) ⇒ Object
Filter to all posts near a particular post number
338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 |
# File 'lib/topic_view.rb', line 338 def filter_posts_near(post_number) posts_before = (@limit.to_f / 4).floor posts_before = 1 if posts_before.zero? sort_order = get_sort_order(post_number) before_post_ids = @filtered_posts .reverse_order .where("posts.sort_order < ?", sort_order) .limit(posts_before) .pluck(:id) post_ids = before_post_ids + @filtered_posts .where("posts.sort_order >= ?", sort_order) .limit(@limit - before_post_ids.length) .pluck(:id) if post_ids.length < @limit post_ids = post_ids + @filtered_posts .reverse_order .where("posts.sort_order < ?", sort_order) .offset(before_post_ids.length) .limit(@limit - post_ids.length) .pluck(:id) end filter_posts_by_ids(post_ids) end |
#filter_posts_paged(page) ⇒ Object
371 372 373 374 375 376 377 378 379 |
# File 'lib/topic_view.rb', line 371 def filter_posts_paged(page) page = [page, 1].max min = @limit * (page - 1) # Sometimes we don't care about the OP, for example when embedding comments min = 1 if min == 0 && @exclude_first filter_posts_by_ids(@filtered_posts.offset(min).limit(@limit).pluck(:id)) end |
#filtered_post_id(post_number) ⇒ Object
682 683 684 |
# File 'lib/topic_view.rb', line 682 def filtered_post_id(post_number) @filtered_posts.where(post_number: post_number).pick(:id) end |
#filtered_post_ids ⇒ Object
660 661 662 663 664 665 666 667 668 669 |
# File 'lib/topic_view.rb', line 660 def filtered_post_ids @filtered_post_ids ||= filtered_post_stream.map do |tuple| if is_mega_topic? tuple else tuple[0] end end end |
#filtered_post_stream ⇒ Object
Returns an array of [id, days_ago] tuples. ‘days_ago` is there for the timeline calculations.
646 647 648 649 650 651 652 653 654 655 656 657 658 |
# File 'lib/topic_view.rb', line 646 def filtered_post_stream @filtered_post_stream ||= begin posts = @filtered_posts columns = [:id] if !is_mega_topic? columns << "(EXTRACT(EPOCH FROM CURRENT_TIMESTAMP - posts.created_at) / 86400)::INT AS days_ago" end posts.pluck(*columns) end end |
#gaps ⇒ Object
175 176 177 178 179 180 181 182 183 184 185 186 |
# File 'lib/topic_view.rb', line 175 def gaps return unless @contains_gaps @gaps ||= begin if is_mega_topic? nil else Gaps.new(filtered_post_ids, apply_default_scope(unfiltered_posts).pluck(:id)) end end end |
#group_allowed_user_ids ⇒ Object
504 505 506 507 508 509 |
# File 'lib/topic_view.rb', line 504 def group_allowed_user_ids return @group_allowed_user_ids unless @group_allowed_user_ids.nil? @group_allowed_user_ids = GroupUser.where(group_id: topic_allowed_group_ids).pluck("distinct user_id") end |
#has_bookmarks? ⇒ Boolean
408 409 410 |
# File 'lib/topic_view.rb', line 408 def has_bookmarks? bookmarks.any? end |
#has_deleted? ⇒ Boolean
392 393 394 395 396 397 398 |
# File 'lib/topic_view.rb', line 392 def has_deleted? @predelete_filtered_posts .with_deleted .where("posts.deleted_at IS NOT NULL") .where("posts.post_number > 1") .exists? end |
#highest_post_number ⇒ Object
This is pending a larger refactor, that allows custom orders for now we need to look for the highest_post_number in the stream the cache on topics is not correct if there are deleted posts at the end of the stream (for mods), nor is it correct for filtered streams
636 637 638 |
# File 'lib/topic_view.rb', line 636 def highest_post_number @highest_post_number ||= @filtered_posts.maximum(:post_number) end |
#image_url ⇒ Object
300 301 302 303 |
# File 'lib/topic_view.rb', line 300 def image_url return @topic.image_url if @post_number == 1 desired_post&.image_url end |
#is_mega_topic? ⇒ Boolean
686 687 688 |
# File 'lib/topic_view.rb', line 686 def is_mega_topic? @is_mega_topic ||= (@topic.posts_count >= MEGA_TOPIC_POSTS_COUNT) end |
#last_post ⇒ Object
188 189 190 191 |
# File 'lib/topic_view.rb', line 188 def last_post return nil if @posts.blank? @last_post ||= @posts.last end |
#last_post_id ⇒ Object
690 691 692 |
# File 'lib/topic_view.rb', line 690 def last_post_id @filtered_posts.reverse_order.pick(:id) end |
#like_count ⇒ Object
286 287 288 289 |
# File 'lib/topic_view.rb', line 286 def like_count return nil if @post_number > 1 # only show for topic URLs @topic.like_count end |
#link_counts ⇒ Object
598 599 600 |
# File 'lib/topic_view.rb', line 598 def link_counts @link_counts ||= TopicLink.counts_for(@guardian, @topic, posts) end |
#links ⇒ Object
535 536 537 |
# File 'lib/topic_view.rb', line 535 def links @links ||= TopicLink.topic_map(@guardian, @topic.id) end |
#mentioned_users ⇒ Object
708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 |
# File 'lib/topic_view.rb', line 708 def mentioned_users @mentioned_users ||= begin mentions = @posts.to_h { |p| [p.id, p.mentions] }.reject { |_, v| v.empty? } usernames = mentions.values usernames.flatten! usernames.uniq! users = User.where(username: usernames).includes(:user_status).index_by(&:username) mentions.reduce({}) do |hash, (post_id, post_mentioned_usernames)| hash[post_id] = post_mentioned_usernames.map { |username| users[username] }.compact hash end end end |
#next_page ⇒ Object
197 198 199 200 201 202 203 204 |
# File 'lib/topic_view.rb', line 197 def next_page @next_page ||= begin if last_post && highest_post_number && (highest_post_number > last_post.post_number) @page + 1 end end end |
#next_page_path ⇒ Object
214 215 216 |
# File 'lib/topic_view.rb', line 214 def next_page_path "#{relative_url}?page=#{next_page}" end |
#page_title ⇒ Object
226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 |
# File 'lib/topic_view.rb', line 226 def page_title title = @topic.title if @post_number > 1 title += " - " post = @topic.posts.find_by(post_number: @post_number) = post&.user if && @guardian.can_see_post?(post) title += I18n.t( "inline_oneboxer.topic_page_title_post_number_by_user", post_number: @post_number, username: .username, ) else title += I18n.t("inline_oneboxer.topic_page_title_post_number", post_number: @post_number) end end if SiteSetting.topic_page_title_includes_category if @topic.category_id != SiteSetting.uncategorized_category_id && @topic.category_id && @topic.category title += " - #{@topic.category.name}" elsif SiteSetting.tagging_enabled && .exists? title += " - #{.order("tags.#{Tag.topic_count_column(@guardian)} DESC").first.name}" end end title end |
#participant_count ⇒ Object
464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 |
# File 'lib/topic_view.rb', line 464 def participant_count @participant_count ||= begin if participants.size == MAX_PARTICIPANTS if @topic.posts_count > MAX_POSTS_COUNT_PARTICIPANTS @topic.participant_count else sql = <<~SQL SELECT COUNT(DISTINCT user_id) FROM posts WHERE id IN (:post_ids) AND user_id IS NOT NULL SQL DB.query_single(sql, post_ids: unfiltered_post_ids).first.to_i end else participants.size end end end |
#participants ⇒ Object
485 486 487 488 489 490 491 492 493 494 495 |
# File 'lib/topic_view.rb', line 485 def participants @participants ||= begin participants = {} User .where(id: post_counts_by_user.keys) .includes(:primary_group, :flair_group) .each { |u| participants[u.id] = u } participants end end |
#pending_posts ⇒ Object
576 577 578 579 |
# File 'lib/topic_view.rb', line 576 def pending_posts @pending_posts ||= ReviewableQueuedPost.pending.where(target_created_by: @user, topic: @topic).order(:created_at) end |
#pm_params ⇒ Object
602 603 604 |
# File 'lib/topic_view.rb', line 602 def pm_params @pm_params ||= TopicQuery.new(@user).get_pm_params(topic) end |
#post_counts_by_user ⇒ Object
429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 |
# File 'lib/topic_view.rb', line 429 def post_counts_by_user @post_counts_by_user ||= begin if is_mega_topic? {} else sql = <<~SQL SELECT user_id, count(*) AS count_all FROM posts WHERE topic_id = :topic_id AND post_type IN (:post_types) AND user_id IS NOT NULL AND posts.deleted_at IS NULL AND action_code IS NULL GROUP BY user_id ORDER BY count_all DESC LIMIT #{MAX_PARTICIPANTS} SQL Hash[ *DB.query_single( sql, topic_id: @topic.id, post_types: Topic.visible_post_types(@guardian&.user), ) ] end end end |
#prev_page ⇒ Object
193 194 195 |
# File 'lib/topic_view.rb', line 193 def prev_page @page > 1 && posts.size > 0 ? @page - 1 : nil end |
#prev_page_path ⇒ Object
206 207 208 209 210 211 212 |
# File 'lib/topic_view.rb', line 206 def prev_page_path if prev_page > 1 "#{relative_url}?page=#{prev_page}" else relative_url end end |
#primary_group_names ⇒ Object
321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 |
# File 'lib/topic_view.rb', line 321 def primary_group_names return @group_names if @group_names primary_group_ids = Set.new @posts.each do |p| primary_group_ids << p.user.primary_group_id if p.user.try(:primary_group_id) end result = {} unless primary_group_ids.empty? Group.where(id: primary_group_ids.to_a).pluck(:id, :name).each { |g| result[g[0]] = g[1] } end @group_names = result end |
#published_page ⇒ Object
704 705 706 |
# File 'lib/topic_view.rb', line 704 def published_page @topic.published_page end |
#published_time ⇒ Object
291 292 293 294 295 296 297 298 |
# File 'lib/topic_view.rb', line 291 def published_time return nil if desired_post.blank? if desired_post.wiki && desired_post.post_number == 1 && desired_post.revisions.size > 0 desired_post.revisions.last.updated_at.strftime("%FT%T%:z") else desired_post.created_at.strftime("%FT%T%:z") end end |
#queued_posts_count ⇒ Object
700 701 702 |
# File 'lib/topic_view.rb', line 700 def queued_posts_count ReviewableQueuedPost.viewable_by(@user).where(topic_id: @topic.id).pending.count end |
#read?(post_number) ⇒ Boolean
387 388 389 390 |
# File 'lib/topic_view.rb', line 387 def read?(post_number) return true unless @user read_posts_set.include?(post_number) end |
#read_time ⇒ Object
275 276 277 278 279 280 281 282 283 284 |
# File 'lib/topic_view.rb', line 275 def read_time return nil if @post_number > 1 # only show for topic URLs if @topic.word_count && SiteSetting.read_time_word_count > 0 [ @topic.word_count / SiteSetting.read_time_word_count, @topic.posts_count * MIN_POST_READ_TIME / 60, ].max.ceil end end |
#recent_posts ⇒ Object
640 641 642 |
# File 'lib/topic_view.rb', line 640 def recent_posts @filtered_posts.unscope(:order).by_newest.with_user.first(25) end |
#related_messages ⇒ Object
623 624 625 626 627 628 629 |
# File 'lib/topic_view.rb', line 623 def if @include_related @related_messages ||= TopicQuery.new(@user).(topic, pm_params: pm_params) else nil end end |
#relative_url ⇒ Object
222 223 224 |
# File 'lib/topic_view.rb', line 222 def relative_url "#{@topic.relative_url}#{@print ? "/print" : ""}" end |
#reviewable_counts ⇒ Object
539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 |
# File 'lib/topic_view.rb', line 539 def reviewable_counts @reviewable_counts ||= begin sql = <<~SQL SELECT target_id, MAX(r.id) reviewable_id, COUNT(*) total, SUM(CASE WHEN s.status = :pending THEN 1 ELSE 0 END) pending FROM reviewables r JOIN reviewable_scores s ON reviewable_id = r.id WHERE r.target_id IN (:post_ids) AND r.target_type = 'Post' AND COALESCE(s.reason, '') != 'category' GROUP BY target_id SQL counts = {} DB .query(sql, pending: ReviewableScore.statuses[:pending], post_ids: @posts.map(&:id)) .each do |row| counts[row.target_id] = { total: row.total, pending: row.pending, reviewable_id: row.reviewable_id, } end counts end end |
#show_read_indicator? ⇒ Boolean
155 156 157 158 159 |
# File 'lib/topic_view.rb', line 155 def show_read_indicator? return false if !@user || !topic. topic.allowed_groups.any? { |group| group.publish_read_state? && group.users.include?(@user) } end |
#suggested_topics ⇒ Object
606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 |
# File 'lib/topic_view.rb', line 606 def suggested_topics if @include_suggested @suggested_topics ||= begin kwargs = DiscoursePluginRegistry.apply_modifier( :topic_view_suggested_topics_options, { include_random: true, pm_params: pm_params }, self, ) TopicQuery.new(@user).list_suggested_for(topic, **kwargs) end else nil end end |
#summarizable? ⇒ Boolean
725 726 727 |
# File 'lib/topic_view.rb', line 725 def summarizable? Summarization::Base.can_see_summary?(@topic, @user) end |
#summary(opts = {}) ⇒ Object
268 269 270 271 272 273 |
# File 'lib/topic_view.rb', line 268 def summary(opts = {}) return nil if desired_post.blank? # TODO, this is actually quite slow, should be cached in the post table excerpt = desired_post.excerpt(500, opts.merge(strip_links: true, text_entities: true)) (excerpt || "").gsub(/\n/, " ").strip end |
#title ⇒ Object
255 256 257 |
# File 'lib/topic_view.rb', line 255 def title @topic.title end |
#topic_allowed_group_ids ⇒ Object
497 498 499 500 501 502 |
# File 'lib/topic_view.rb', line 497 def topic_allowed_group_ids @topic_allowed_group_ids ||= begin @topic.allowed_groups.map(&:id) end end |
#topic_user ⇒ Object
400 401 402 403 404 405 406 |
# File 'lib/topic_view.rb', line 400 def topic_user @topic_user ||= begin return nil if @user.blank? @topic.topic_users.find_by(user_id: @user.id) end end |
#unfiltered_post_ids ⇒ Object
671 672 673 674 675 676 677 678 679 680 |
# File 'lib/topic_view.rb', line 671 def unfiltered_post_ids @unfiltered_post_ids ||= begin if @contains_gaps unfiltered_posts.pluck(:id) else filtered_post_ids end end end |