# frozen_string_literal: true class PostBookmarkable < BaseBookmarkable include TopicPostBookmarkableHelper def self.model Post end def self.serializer UserPostBookmarkSerializer end def self.preload_associations [{ topic: %i[tags category] }, :user] end def self.list_query(user, guardian) topics = Topic.listable_topics.secured(guardian) pms = Topic.private_messages_for_user(user) post_bookmarks = user .bookmarks_of_type("Post") .joins( "INNER JOIN posts ON posts.id = bookmarks.bookmarkable_id AND bookmarks.bookmarkable_type = 'Post'", ) .joins("LEFT JOIN topics ON topics.id = posts.topic_id") .joins("LEFT JOIN topic_users ON topic_users.topic_id = topics.id") .where("topic_users.user_id = ?", user.id) guardian.filter_allowed_categories( post_bookmarks.merge(topics.or(pms)).merge(Post.secured(guardian)), ) end def self.search_query(bookmarks, query, ts_query, &bookmarkable_search) bookmarkable_search.call( bookmarks.joins( "LEFT JOIN post_search_data ON post_search_data.post_id = bookmarks.bookmarkable_id AND bookmarks.bookmarkable_type = 'Post'", ), "#{ts_query} @@ post_search_data.search_data", ) end def self.reminder_handler(bookmark) send_reminder_notification( bookmark, topic_id: bookmark.bookmarkable.topic_id, post_number: bookmark.bookmarkable.post_number, data: { title: bookmark.bookmarkable.topic.title, bookmarkable_url: bookmark.bookmarkable.url, }, ) end def self.reminder_conditions(bookmark) bookmark.bookmarkable.present? && bookmark.bookmarkable.topic.present? && self.can_see?(bookmark.user.guardian, bookmark) end def self.can_see?(guardian, bookmark) guardian.can_see_post?(bookmark.bookmarkable) end def self.bookmark_metadata(bookmark, user) { topic_bookmarked: Bookmark.for_user_in_topic(user.id, bookmark.bookmarkable.topic_id).exists?, } end def self.validate_before_create(guardian, bookmarkable) if bookmarkable.blank? || bookmarkable.topic.blank? || !guardian.can_see_topic?(bookmarkable.topic) || !guardian.can_see_post?(bookmarkable) raise Discourse::InvalidAccess end end def self.after_create(guardian, bookmark, opts) sync_topic_user_bookmarked(guardian.user, bookmark.bookmarkable.topic, opts) end def self.after_destroy(guardian, bookmark, opts) sync_topic_user_bookmarked(guardian.user, bookmark.bookmarkable.topic, opts) end def self.cleanup_deleted related_topics = DB.query(<<~SQL, grace_time: 3.days.ago) DELETE FROM bookmarks b USING topics t, posts p WHERE t.id = p.topic_id AND b.bookmarkable_id = p.id AND b.bookmarkable_type = 'Post' AND (t.deleted_at < :grace_time OR p.deleted_at < :grace_time) RETURNING t.id AS topic_id SQL related_topics_ids = related_topics.map(&:topic_id).uniq related_topics_ids.each do |topic_id| Jobs.enqueue(:sync_topic_user_bookmarked, topic_id: topic_id) end end end