Class: PostDestroyer
- Inherits:
-
Object
- Object
- PostDestroyer
- Defined in:
- lib/post_destroyer.rb
Overview
How a post is deleted is affected by who is performing the action. this class contains the logic to delete it.
Class Method Summary collapse
- .delete_with_replies(performed_by, post, reviewable = nil, defer_reply_flags: true) ⇒ Object
- .destroy_old_hidden_posts ⇒ Object
- .destroy_stubs ⇒ Object
Instance Method Summary collapse
- #destroy ⇒ Object
-
#initialize(user, post, opts = {}) ⇒ PostDestroyer
constructor
A new instance of PostDestroyer.
-
#mark_for_deletion(delete_removed_posts_after = SiteSetting.delete_removed_posts_after) ⇒ Object
When a user ‘deletes’ their own post.
-
#perform_delete ⇒ Object
When a post is properly deleted.
- #permanent? ⇒ Boolean
- #recover ⇒ Object
- #staff_recovered ⇒ Object
- #user_recovered ⇒ Object
Constructor Details
#initialize(user, post, opts = {}) ⇒ PostDestroyer
Returns a new instance of PostDestroyer.
55 56 57 58 59 60 |
# File 'lib/post_destroyer.rb', line 55 def initialize(user, post, opts = {}) @user = user @post = post @topic = post.topic || Topic.with_deleted.find_by(id: @post.topic_id) @opts = opts end |
Class Method Details
.delete_with_replies(performed_by, post, reviewable = nil, defer_reply_flags: true) ⇒ Object
43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/post_destroyer.rb', line 43 def self.delete_with_replies(performed_by, post, reviewable = nil, defer_reply_flags: true) reply_ids = post.reply_ids(Guardian.new(performed_by), only_replies_to_single_post: false) replies = Post.where(id: reply_ids.map { |r| r[:id] }) PostDestroyer.new(performed_by, post, reviewable: reviewable).destroy = { defer_flags: defer_reply_flags } if SiteSetting.notify_users_after_responses_deleted_on_flagged_post .merge!({ reviewable: reviewable, notify_responders: true, parent_post: post }) end replies.each { |reply| PostDestroyer.new(performed_by, reply, ).destroy } end |
.destroy_old_hidden_posts ⇒ Object
8 9 10 11 12 13 |
# File 'lib/post_destroyer.rb', line 8 def self.destroy_old_hidden_posts Post .where(deleted_at: nil, hidden: true) .where("hidden_at < ?", 30.days.ago) .find_each { |post| PostDestroyer.new(Discourse.system_user, post).destroy } end |
.destroy_stubs ⇒ Object
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
# File 'lib/post_destroyer.rb', line 15 def self.destroy_stubs context = I18n.t("remove_posts_deleted_by_author") # exclude deleted topics and posts that are actively flagged Post .where(deleted_at: nil, user_deleted: true) .where( "NOT EXISTS ( SELECT 1 FROM topics t WHERE t.deleted_at IS NOT NULL AND t.id = posts.topic_id )", ) .where("updated_at < ?", SiteSetting.delete_removed_posts_after.hours.ago) .where( "NOT EXISTS ( SELECT 1 FROM post_actions pa WHERE pa.post_id = posts.id AND pa.deleted_at IS NULL AND pa.deferred_at IS NULL AND pa.post_action_type_id IN (?) )", PostActionType.notify_flag_type_ids, ) .find_each { |post| PostDestroyer.new(Discourse.system_user, post, context: context).destroy } end |
Instance Method Details
#destroy ⇒ Object
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/post_destroyer.rb', line 62 def destroy delete_removed_posts_after = @opts[:delete_removed_posts_after] || SiteSetting.delete_removed_posts_after if delete_removed_posts_after < 1 || post_is_reviewable? || Guardian.new(@user).can_moderate_topic?(@topic) || permanent? perform_delete elsif @user.id == @post.user_id mark_for_deletion(delete_removed_posts_after) end UserActionManager.post_destroyed(@post) DiscourseEvent.trigger(:post_destroyed, @post, @opts, @user) if WebHook.active_web_hooks(:post_destroyed).exists? payload = WebHook.generate_payload(:post, @post) WebHook.enqueue_post_hooks(:post_destroyed, @post, payload) end Jobs.enqueue(:sync_topic_user_bookmarked, topic_id: @topic.id) if @topic is_first_post = @post.is_first_post? && @topic if is_first_post UserProfile.remove_featured_topic_from_all_profiles(@topic) UserActionManager.topic_destroyed(@topic) DiscourseEvent.trigger(:topic_destroyed, @topic, @user) if WebHook.active_web_hooks(:topic_destroyed).exists? topic_view = TopicView.new(@topic.id, Discourse.system_user, skip_staff_action: true) topic_payload = WebHook.generate_payload(:topic, topic_view, WebHookTopicViewSerializer) WebHook.enqueue_topic_hooks(:topic_destroyed, @topic, topic_payload) end if SiteSetting.tos_topic_id == @topic.id || SiteSetting.privacy_topic_id == @topic.id Discourse.clear_urls! end end end |
#mark_for_deletion(delete_removed_posts_after = SiteSetting.delete_removed_posts_after) ⇒ Object
When a user ‘deletes’ their own post. We just change the text.
252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 |
# File 'lib/post_destroyer.rb', line 252 def mark_for_deletion(delete_removed_posts_after = SiteSetting.delete_removed_posts_after) I18n.with_locale(SiteSetting.default_locale) do # don't call revise from within transaction, high risk of deadlock key = ( if @post.is_first_post? "js.topic.deleted_by_author_simple" else "js.post.deleted_by_author_simple" end ) @post.revise( @user, { raw: I18n.t(key) }, force_new_version: true, deleting_post: true, skip_validations: true, ) Post.transaction do @post.update_column(:user_deleted, true) @post.topic_links.each(&:destroy) @post.topic.update_column(:closed, true) if @post.is_first_post? end end end |
#perform_delete ⇒ Object
When a post is properly deleted. Well, it’s still soft deleted, but it will no longer show up in the topic Permanent option allows to hard delete.
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 |
# File 'lib/post_destroyer.rb', line 165 def perform_delete # All posts in the topic must be force deleted if the first is force # deleted (except @post which is destroyed by current instance). if @topic && @post.is_first_post? && permanent? @topic.ordered_posts.with_deleted.reverse_order.find_each do |post| PostDestroyer.new(@user, post, @opts).destroy if post.id != @post.id end end Post.transaction do permanent? ? @post.destroy! : @post.trash!(@user) if @post.topic make_previous_post_the_last_one mark_topic_changed clear_user_posted_flag end Topic.reset_highest(@post.topic_id) trash_public_post_actions trash_revisions trash_user_actions remove_associated_replies remove_associated_notifications if @user.id != @post.user_id && !@opts[:skip_staff_log] if @post.topic && @post.is_first_post? StaffActionLogger.new(@user).log_topic_delete_recover( @post.topic, permanent? ? "delete_topic_permanently" : "delete_topic", @opts.slice(:context), ) else StaffActionLogger.new(@user).log_post_deletion( @post, **@opts.slice(:context), permanent: permanent?, ) end end if @topic && @post.is_first_post? permanent? ? @topic.destroy! : @topic.trash!(@user) PublishedPage.unpublish!(@user, @topic) if @topic.published_page end TopicLink.where(link_post_id: @post.id).destroy_all update_associated_category_latest_topic update_user_counts if !permanent? TopicUser.update_post_action_cache(post_id: @post.id) if permanent? if @post.topic && @post.is_first_post? UserHistory.where(topic_id: @post.topic.id).update_all(details: "(permanently deleted)") end UserHistory.where(post_id: @post.id).update_all(details: "(permanently deleted)") end DB.after_commit do if @opts[:reviewable] notify_deletion( @opts[:reviewable], { notify_responders: @opts[:notify_responders], parent_post: @opts[:parent_post] }, ) if @post.reviewable_flag && SiteSetting.notify_users_after_responses_deleted_on_flagged_post ignore(@post.reviewable_flag) end elsif reviewable = @post.reviewable_flag @opts[:defer_flags] ? ignore(reviewable) : agree(reviewable) end end end update_imap_sync(@post, true) if @post.topic&.deleted_at feature_users_in_the_topic if @post.topic @post.publish_change_to_clients!(permanent? ? :destroyed : :deleted) if @post.topic if @post.topic && @post.post_number == 1 TopicTrackingState.send(permanent? ? :publish_destroy : :publish_delete, @post.topic) end end |
#permanent? ⇒ Boolean
246 247 248 249 |
# File 'lib/post_destroyer.rb', line 246 def permanent? @opts[:force_destroy] || (@opts[:permanent] && @user == @post.user && @post.topic.) end |
#recover ⇒ Object
98 99 100 101 102 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 |
# File 'lib/post_destroyer.rb', line 98 def recover if (post_is_reviewable? || Guardian.new(@user).can_moderate_topic?(@post.topic)) && @post.deleted_at staff_recovered elsif @user.staff? || @user.id == @post.user_id user_recovered end @topic.update_column(:user_id, Discourse::SYSTEM_USER_ID) if !@topic.user_id @topic.recover!(@user) if @post.is_first_post? @topic.update_statistics Topic.publish_stats_to_clients!(@topic.id, :recovered) UserActionManager.post_created(@post) DiscourseEvent.trigger(:post_recovered, @post, @opts, @user) Jobs.enqueue(:sync_topic_user_bookmarked, topic_id: @topic.id) if @topic Jobs.enqueue(:notify_mailing_list_subscribers, post_id: @post.id) if @post.is_first_post? UserActionManager.topic_created(@topic) DiscourseEvent.trigger(:topic_recovered, @topic, @user) if @user.id != @post.user_id StaffActionLogger.new(@user).log_topic_delete_recover( @topic, "recover_topic", @opts.slice(:context), ) end update_imap_sync(@post, false) if SiteSetting.tos_topic_id == @topic.id || SiteSetting.privacy_topic_id == @topic.id Discourse.clear_urls! end end end |
#staff_recovered ⇒ Object
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
# File 'lib/post_destroyer.rb', line 133 def staff_recovered new_post_attrs = { user_deleted: false } new_post_attrs[:user_id] = Discourse::SYSTEM_USER_ID if !@post.user_id @post.update_columns(new_post_attrs) @post.recover! mark_topic_changed if @post.topic && !@post.topic. if = @post.user if @post.is_first_post? .user_stat.topic_count += 1 else .user_stat.post_count += 1 end .user_stat.save! end if @post.is_first_post? # Update stats of all people who replied update_post_counts(:increment) end end # skip also publishing topic stats because they weren't updated yet @post.publish_change_to_clients! :recovered, { skip_topic_stats: true } TopicTrackingState.publish_recover(@post.topic) if @post.topic && @post.is_first_post? end |
#user_recovered ⇒ Object
279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 |
# File 'lib/post_destroyer.rb', line 279 def user_recovered return unless @post.user_deleted? Post.transaction do @post.update_column(:user_deleted, false) @post.skip_unique_check = true @post.topic.update_column(:closed, false) if @post.is_first_post? end # has internal transactions, if we nest then there are some very high risk deadlocks last_revision = @post.revisions.last if last_revision.present? && last_revision.modifications["raw"].present? @post.revise(@user, { raw: last_revision.modifications["raw"][0] }, force_new_version: true) end end |