diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml index 6dda02e29bb..a75b9d48963 100644 --- a/config/locales/server.en.yml +++ b/config/locales/server.en.yml @@ -275,6 +275,7 @@ en: not_accepting_pms: "Sorry, %{username} is not accepting messages at the moment." max_pm_recepients: "Sorry, you can send a message to maximum %{recipients_limit} recipients." pm_reached_recipients_limit: "Sorry, you can't have more than %{recipients_limit} recipients in a message." + removed_direct_reply_full_quotes: "Automatically removed quote of whole previous post." just_posted_that: "is too similar to what you recently posted" invalid_characters: "contains invalid characters" diff --git a/lib/cooked_post_processor.rb b/lib/cooked_post_processor.rb index ace18156c4a..301ce313553 100644 --- a/lib/cooked_post_processor.rb +++ b/lib/cooked_post_processor.rb @@ -32,6 +32,7 @@ class CookedPostProcessor def post_process(bypass_bump = false) DistributedMutex.synchronize("post_process_#{@post.id}") do DiscourseEvent.trigger(:before_post_process_cooked, @doc, @post) + removed_direct_reply_full_quotes post_process_oneboxes post_process_images post_process_quotes @@ -85,6 +86,28 @@ class CookedPostProcessor end end + def removed_direct_reply_full_quotes + return if @post.post_number == 1 + + num_quotes = @doc.css("aside.quote").size + return if num_quotes != 1 + + prev = Post.where('post_number < ? AND topic_id = ? AND post_type = ? AND not hidden', @post.post_number, @post.topic_id, Post.types[:regular]).order('post_number desc').limit(1).pluck(:raw).first + return if !prev + + new_raw = @post.raw.gsub(/\[quote[^\]]*\]\s*#{Regexp.quote(prev.strip)}\s*\[\/quote\]/, '') + return if @post.raw == new_raw + + PostRevisor.new(@post).revise!( + Discourse.system_user, + { + raw: new_raw.strip, + edit_reason: I18n.t(:removed_direct_reply_full_quotes) + }, + skip_validations: true + ) + end + def add_image_placeholder!(img) src = img["src"].sub(/^https?:/i, "") diff --git a/spec/components/cooked_post_processor_spec.rb b/spec/components/cooked_post_processor_spec.rb index 7990b39fad6..7decf8cfb82 100644 --- a/spec/components/cooked_post_processor_spec.rb +++ b/spec/components/cooked_post_processor_spec.rb @@ -1144,4 +1144,32 @@ describe CookedPostProcessor do end + context "remove direct reply full quote" do + let(:topic) { Fabricate(:topic) } + + it 'works' do + post = Fabricate(:post, topic: topic, raw: "this is the first post") + hidden = Fabricate(:post, topic: topic, hidden: true, raw: "this is the second post") + small_action = Fabricate(:post, topic: topic, post_type: Post.types[:small_action]) + raw = <<~RAW + [quote="#{post.user.username}, post:#{post.post_number}, topic:#{topic.id}"] + this is the first post + [/quote] + + and this is the third reply + RAW + reply = Fabricate(:post, topic: topic, raw: raw) + + cpp = CookedPostProcessor.new(reply) + cpp.removed_direct_reply_full_quotes + + expect(topic.posts).to eq([post, hidden, small_action, reply]) + expect(reply.raw).to eq("and this is the third reply") + expect(reply.revisions.count).to eq(1) + expect(reply.revisions.first.modifications["raw"]).to eq([raw, reply.raw]) + expect(reply.revisions.first.modifications["edit_reason"][1]).to eq(I18n.t(:removed_direct_reply_full_quotes)) + end + + end + end diff --git a/spec/services/username_changer_spec.rb b/spec/services/username_changer_spec.rb index 0476615fafd..c4281a403a3 100644 --- a/spec/services/username_changer_spec.rb +++ b/spec/services/username_changer_spec.rb @@ -335,7 +335,7 @@ describe UsernameChanger do Lorem ipsum [quote="foo, post:1, topic:#{quoted_post.topic.id}"] - quoted post + quoted [/quote] RAW end @@ -345,7 +345,7 @@ describe UsernameChanger do Lorem ipsum [quote="bar, post:1, topic:#{quoted_post.topic.id}"] - quoted post + quoted [/quote] RAW end @@ -358,7 +358,7 @@ describe UsernameChanger do
-HTMLquoted post
+quoted