mirror of
https://github.com/discourse/discourse.git
synced 2024-12-15 09:43:46 +08:00
30990006a9
This reduces chances of errors where consumers of strings mutate inputs and reduces memory usage of the app. Test suite passes now, but there may be some stuff left, so we will run a few sites on a branch prior to merging
96 lines
3.0 KiB
Ruby
96 lines
3.0 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
class QuotedPost < ActiveRecord::Base
|
|
belongs_to :post
|
|
belongs_to :quoted_post, class_name: 'Post'
|
|
|
|
# NOTE we already have a path that does this for topic links,
|
|
# however topic links exclude quotes and links within a topic
|
|
# we are double parsing this fragment, this may be worth optimising later
|
|
def self.extract_from(post)
|
|
|
|
doc = Nokogiri::HTML.fragment(post.cooked)
|
|
|
|
uniq = {}
|
|
|
|
doc.css("aside.quote[data-topic]").each do |a|
|
|
topic_id = a['data-topic'].to_i
|
|
post_number = a['data-post'].to_i
|
|
|
|
next if topic_id == 0 || post_number == 0
|
|
next if uniq[[topic_id, post_number]]
|
|
next if post.topic_id == topic_id && post.post_number == post_number
|
|
|
|
uniq[[topic_id, post_number]] = true
|
|
end
|
|
|
|
if uniq.length == 0
|
|
DB.exec("DELETE FROM quoted_posts WHERE post_id = :post_id", post_id: post.id)
|
|
else
|
|
|
|
args = {
|
|
post_id: post.id,
|
|
topic_ids: uniq.keys.map(&:first),
|
|
post_numbers: uniq.keys.map(&:second)
|
|
}
|
|
|
|
DB.exec(<<~SQL, args)
|
|
INSERT INTO quoted_posts (post_id, quoted_post_id, created_at, updated_at)
|
|
SELECT :post_id, p.id, current_timestamp, current_timestamp
|
|
FROM posts p
|
|
JOIN (
|
|
SELECT
|
|
unnest(ARRAY[:topic_ids]) topic_id,
|
|
unnest(ARRAY[:post_numbers]) post_number
|
|
) X ON X.topic_id = p.topic_id AND X.post_number = p.post_number
|
|
LEFT JOIN quoted_posts q on q.post_id = :post_id AND q.quoted_post_id = p.id
|
|
WHERE q.id IS NULL
|
|
SQL
|
|
|
|
DB.exec(<<~SQL, args)
|
|
DELETE FROM quoted_posts
|
|
WHERE post_id = :post_id
|
|
AND id IN (
|
|
SELECT q1.id FROM quoted_posts q1
|
|
LEFT JOIN posts p1 ON p1.id = q1.quoted_post_id
|
|
LEFT JOIN (
|
|
SELECT
|
|
unnest(ARRAY[:topic_ids]) topic_id,
|
|
unnest(ARRAY[:post_numbers]) post_number
|
|
) X on X.topic_id = p1.topic_id AND X.post_number = p1.post_number
|
|
WHERE q1.post_id = :post_id AND X.topic_id IS NULL
|
|
)
|
|
SQL
|
|
end
|
|
|
|
# simplest place to add this code
|
|
reply_quoted = false
|
|
|
|
if post.reply_to_post_number
|
|
reply_post_id = Post.where(topic_id: post.topic_id, post_number: post.reply_to_post_number).pluck(:id).first
|
|
reply_quoted = reply_post_id.present? && QuotedPost.where(post_id: post.id, quoted_post_id: reply_post_id).count > 0
|
|
end
|
|
|
|
if reply_quoted != post.reply_quoted
|
|
post.update_columns(reply_quoted: reply_quoted)
|
|
end
|
|
|
|
end
|
|
end
|
|
|
|
# == Schema Information
|
|
#
|
|
# Table name: quoted_posts
|
|
#
|
|
# id :integer not null, primary key
|
|
# post_id :integer not null
|
|
# quoted_post_id :integer not null
|
|
# created_at :datetime not null
|
|
# updated_at :datetime not null
|
|
#
|
|
# Indexes
|
|
#
|
|
# index_quoted_posts_on_post_id_and_quoted_post_id (post_id,quoted_post_id) UNIQUE
|
|
# index_quoted_posts_on_quoted_post_id_and_post_id (quoted_post_id,post_id) UNIQUE
|
|
#
|