mirror of
https://github.com/discourse/discourse.git
synced 2024-11-22 09:42:02 +08:00
FIX: First Quote badge bust
Feature: track quoted posts
This commit is contained in:
parent
4c25fedf70
commit
2d0def9940
|
@ -123,6 +123,7 @@ class PostsController < ApplicationController
|
|||
revisor = PostRevisor.new(post)
|
||||
if revisor.revise!(current_user, params[:post][:raw], edit_reason: params[:post][:edit_reason])
|
||||
TopicLink.extract_from(post)
|
||||
QuotedPost.extract_from(post)
|
||||
end
|
||||
|
||||
if post.errors.present?
|
||||
|
|
|
@ -45,17 +45,16 @@ SQL
|
|||
SQL
|
||||
|
||||
FirstQuote = <<SQL
|
||||
SELECT l.user_id, l.post_id, l.created_at granted_at
|
||||
SELECT ids.user_id, q.post_id, q.created_at granted_at
|
||||
FROM
|
||||
(
|
||||
SELECT MIN(l1.id) id
|
||||
FROM topic_links l1
|
||||
JOIN badge_posts p1 ON p1.id = l1.post_id
|
||||
JOIN badge_posts p2 ON p2.id = l1.link_post_id
|
||||
WHERE NOT reflection AND quote
|
||||
GROUP BY l1.user_id
|
||||
SELECT p1.user_id, MIN(q1.id) id
|
||||
FROM quoted_posts q1
|
||||
JOIN badge_posts p1 ON p1.id = q1.post_id
|
||||
JOIN badge_posts p2 ON p2.id = q1.quoted_post_id
|
||||
GROUP BY p1.user_id
|
||||
) ids
|
||||
JOIN topic_links l ON l.id = ids.id
|
||||
JOIN quoted_posts q ON q.id = ids.id
|
||||
SQL
|
||||
|
||||
FirstLink = <<SQL
|
||||
|
|
|
@ -93,6 +93,7 @@ class Post < ActiveRecord::Base
|
|||
super
|
||||
update_flagged_posts_count
|
||||
TopicLink.extract_from(self)
|
||||
QuotedPost.extract_from(self)
|
||||
if topic && topic.category_id && topic.category
|
||||
topic.category.update_latest
|
||||
end
|
||||
|
@ -336,7 +337,9 @@ class Post < ActiveRecord::Base
|
|||
update_columns(cooked: new_cooked, baked_at: Time.new, baked_version: BAKED_VERSION)
|
||||
|
||||
# Extracts urls from the body
|
||||
TopicLink.extract_from self
|
||||
TopicLink.extract_from(self)
|
||||
QuotedPost.extract_from(self)
|
||||
|
||||
# make sure we trigger the post process
|
||||
trigger_post_process(true)
|
||||
|
||||
|
|
46
app/models/quoted_post.rb
Normal file
46
app/models/quoted_post.rb
Normal file
|
@ -0,0 +1,46 @@
|
|||
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 = {}
|
||||
ids = []
|
||||
|
||||
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]]
|
||||
uniq[[topic_id,post_number]] = true
|
||||
|
||||
|
||||
# It would be so much nicer if we used post_id in quotes
|
||||
results = exec_sql "INSERT INTO quoted_posts(post_id, quoted_post_id, created_at, updated_at)
|
||||
SELECT :post_id, id, current_timestamp, current_timestamp
|
||||
FROM posts
|
||||
WHERE post_number = :post_number AND
|
||||
topic_id = :topic_id
|
||||
RETURNING quoted_post_id
|
||||
", post_id: post.id, post_number: post_number, topic_id: topic_id
|
||||
|
||||
results = results.to_a
|
||||
|
||||
if results.length > 0
|
||||
ids << results[0]["quoted_post_id"].to_i
|
||||
end
|
||||
end
|
||||
|
||||
if ids.length > 0
|
||||
exec_sql "DELETE FROM quoted_posts WHERE post_id = :post_id AND quoted_post_id NOT IN (:ids)",
|
||||
post_id: post.id, ids: ids
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -487,6 +487,7 @@ class Topic < ActiveRecord::Base
|
|||
|
||||
# Grab any links that are present
|
||||
TopicLink.extract_from(new_post)
|
||||
QuotedPost.extract_from(new_post)
|
||||
end
|
||||
|
||||
new_post
|
||||
|
|
54
db/migrate/20140715055242_add_quoted_posts.rb
Normal file
54
db/migrate/20140715055242_add_quoted_posts.rb
Normal file
|
@ -0,0 +1,54 @@
|
|||
class AddQuotedPosts < ActiveRecord::Migration
|
||||
def change
|
||||
create_table :quoted_posts do |t|
|
||||
t.integer :post_id, null: false
|
||||
t.integer :quoted_post_id, null: false
|
||||
t.timestamps
|
||||
end
|
||||
|
||||
add_index :quoted_posts, [:post_id, :quoted_post_id], unique: true
|
||||
add_index :quoted_posts, [:quoted_post_id, :post_id], unique: true
|
||||
|
||||
|
||||
# NOTE this can be done in pg but too much of a headache
|
||||
id = 0
|
||||
while id = backfill_batch(id, 1000); end
|
||||
end
|
||||
|
||||
def backfill_batch(start_id, batch_size)
|
||||
|
||||
results = execute <<SQL
|
||||
SELECT id, cooked
|
||||
FROM posts
|
||||
WHERE raw like '%quote=%' AND id > #{start_id}
|
||||
ORDER BY id
|
||||
LIMIT #{batch_size}
|
||||
SQL
|
||||
|
||||
max_id = nil
|
||||
|
||||
results.each do |row|
|
||||
post_id, max_id = row["id"].to_i
|
||||
doc = Nokogiri::HTML.fragment(row["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 uniq[[topic_id,post_number]]
|
||||
uniq[[topic_id,post_number]] = true
|
||||
|
||||
|
||||
execute "INSERT INTO quoted_posts(post_id, quoted_post_id, created_at, updated_at)
|
||||
SELECT #{post_id}, id, created_at, updated_at
|
||||
FROM posts
|
||||
WHERE post_number = #{post_number} AND
|
||||
topic_id = #{topic_id}"
|
||||
end
|
||||
end
|
||||
|
||||
max_id
|
||||
end
|
||||
end
|
|
@ -266,6 +266,7 @@ class PostCreator
|
|||
|
||||
def extract_links
|
||||
TopicLink.extract_from(@post)
|
||||
QuotedPost.extract_from(@post)
|
||||
end
|
||||
|
||||
def track_topic
|
||||
|
|
27
spec/models/quoted_post_spec.rb
Normal file
27
spec/models/quoted_post_spec.rb
Normal file
|
@ -0,0 +1,27 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe QuotedPost do
|
||||
it 'correctly extracts quotes in integration test' do
|
||||
post1 = create_post
|
||||
post2 = create_post(topic_id: post1.topic_id,
|
||||
raw: "[quote=\"#{post1.user.username}, post: 1, topic:#{post1.topic_id}\"]\ntest\n[/quote]\nthis is a test post")
|
||||
|
||||
QuotedPost.find_by(post_id: post2.id, quoted_post_id: post1.id).should_not be_nil
|
||||
end
|
||||
|
||||
it 'correctly handles deltas' do
|
||||
post1 = Fabricate(:post)
|
||||
post2 = Fabricate(:post)
|
||||
|
||||
post2.cooked = <<HTML
|
||||
<aside class="quote" data-post="#{post1.post_number}" data-topic="#{post1.topic_id}"><div class="title"><div class="quote-controls"></div><img width="20" height="20" src="/user_avatar/meta.discourse.org/techapj/20/3281.png" class="avatar">techAPJ said:</div><blockquote><p>When the user will v</p></blockquote></aside>
|
||||
HTML
|
||||
|
||||
QuotedPost.create!(post_id: post2.id, quoted_post_id: 999)
|
||||
|
||||
QuotedPost.extract_from(post2)
|
||||
QuotedPost.where(post_id: post2.id).count.should == 1
|
||||
QuotedPost.find_by(post_id: post2.id, quoted_post_id: post1.id).should_not be_nil
|
||||
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue
Block a user