mirror of
https://github.com/discourse/discourse.git
synced 2025-01-30 05:01:44 +08:00
Extract PostMover from Topic into its own class
This commit is contained in:
parent
1ba18318ac
commit
6024529f81
117
app/models/post_mover.rb
Normal file
117
app/models/post_mover.rb
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
class PostMover
|
||||||
|
attr_reader :original_topic, :destination_topic, :user, :post_ids
|
||||||
|
|
||||||
|
def initialize(original_topic, user, post_ids)
|
||||||
|
@original_topic = original_topic
|
||||||
|
@user = user
|
||||||
|
@post_ids = post_ids
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_topic(id)
|
||||||
|
Topic.transaction do
|
||||||
|
move_posts_to Topic.find_by_id(id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_new_topic(title)
|
||||||
|
Topic.transaction do
|
||||||
|
move_posts_to Topic.create!(
|
||||||
|
user: user,
|
||||||
|
title: title,
|
||||||
|
category: original_topic.category
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def move_posts_to(topic)
|
||||||
|
Guardian.new(user).ensure_can_see! topic
|
||||||
|
@destination_topic = topic
|
||||||
|
|
||||||
|
move_posts_to_destination_topic
|
||||||
|
destination_topic
|
||||||
|
end
|
||||||
|
|
||||||
|
def move_posts_to_destination_topic
|
||||||
|
move_each_post
|
||||||
|
notify_users_that_posts_have_moved
|
||||||
|
update_statistics
|
||||||
|
end
|
||||||
|
|
||||||
|
def move_each_post
|
||||||
|
with_max_post_number do |max_post_number|
|
||||||
|
posts.each_with_index do |post, offset|
|
||||||
|
post.is_first_post? ? copy(post) : move(post, offset + max_post_number)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def copy(post)
|
||||||
|
PostCreator.create(
|
||||||
|
post.user,
|
||||||
|
raw: post.raw,
|
||||||
|
topic_id: destination_topic.id,
|
||||||
|
acting_user: user
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def move(post, post_number)
|
||||||
|
@first_post_number_moved ||= post.post_number
|
||||||
|
|
||||||
|
Post.update_all(
|
||||||
|
[
|
||||||
|
['post_number = :post_number',
|
||||||
|
'topic_id = :topic_id',
|
||||||
|
'sort_order = :post_number'
|
||||||
|
].join(', '),
|
||||||
|
post_number: post_number,
|
||||||
|
topic_id: destination_topic.id
|
||||||
|
],
|
||||||
|
id: post.id,
|
||||||
|
topic_id: original_topic.id
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def update_statistics
|
||||||
|
destination_topic.update_statistics
|
||||||
|
original_topic.update_statistics
|
||||||
|
end
|
||||||
|
|
||||||
|
def notify_users_that_posts_have_moved
|
||||||
|
enqueue_notification_job
|
||||||
|
create_moderator_post_in_original_topic
|
||||||
|
end
|
||||||
|
|
||||||
|
def enqueue_notification_job
|
||||||
|
Jobs.enqueue(
|
||||||
|
:notify_moved_posts,
|
||||||
|
post_ids: post_ids,
|
||||||
|
moved_by_id: user.id
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_moderator_post_in_original_topic
|
||||||
|
original_topic.add_moderator_post(
|
||||||
|
user,
|
||||||
|
I18n.t(
|
||||||
|
"move_posts.moderator_post",
|
||||||
|
count: post_ids.count,
|
||||||
|
topic_link: "[#{destination_topic.title}](#{destination_topic.url})"
|
||||||
|
),
|
||||||
|
post_number: @first_post_number_moved
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def with_max_post_number
|
||||||
|
yield destination_topic.max_post_number + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
def posts
|
||||||
|
@posts ||= begin
|
||||||
|
Post.where(id: post_ids).order(:created_at).tap do |posts|
|
||||||
|
raise Discourse::InvalidParameters.new(:post_ids) if posts.empty?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -447,74 +447,18 @@ class Topic < ActiveRecord::Base
|
||||||
invite
|
invite
|
||||||
end
|
end
|
||||||
|
|
||||||
def move_posts_to_topic(moved_by, post_ids, destination_topic)
|
|
||||||
to_move = posts.where(id: post_ids).order(:created_at)
|
|
||||||
raise Discourse::InvalidParameters.new(:post_ids) if to_move.blank?
|
|
||||||
|
|
||||||
first_post_number = nil
|
|
||||||
Topic.transaction do
|
|
||||||
# Find the max post number in the topic
|
|
||||||
max_post_number = destination_topic.posts.maximum(:post_number) || 0
|
|
||||||
|
|
||||||
to_move.each_with_index do |post, i|
|
|
||||||
if post.post_number == 1
|
|
||||||
# We have a special case for the OP, we copy it instead of deleting it.
|
|
||||||
result = PostCreator.new(post.user,
|
|
||||||
raw: post.raw,
|
|
||||||
topic_id: destination_topic.id,
|
|
||||||
acting_user: moved_by).create
|
|
||||||
else
|
|
||||||
first_post_number ||= post.post_number
|
|
||||||
# Move the post and raise an error if it couldn't be moved
|
|
||||||
row_count = Post.update_all ["post_number = :post_number, topic_id = :topic_id, sort_order = :post_number", post_number: max_post_number+i+1, topic_id: destination_topic.id], id: post.id, topic_id: id
|
|
||||||
raise Discourse::InvalidParameters.new(:post_ids) if row_count == 0
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
first_post_number
|
|
||||||
end
|
|
||||||
|
|
||||||
def max_post_number
|
def max_post_number
|
||||||
posts.maximum(:post_number).to_i
|
posts.maximum(:post_number).to_i
|
||||||
end
|
end
|
||||||
|
|
||||||
def move_posts(moved_by, post_ids, opts)
|
def move_posts(moved_by, post_ids, opts)
|
||||||
|
post_mover = PostMover.new(self, moved_by, post_ids)
|
||||||
|
|
||||||
topic = nil
|
if opts[:destination_topic_id]
|
||||||
first_post_number = nil
|
post_mover.to_topic opts[:destination_topic_id]
|
||||||
|
elsif opts[:title]
|
||||||
if opts[:title].present?
|
post_mover.to_new_topic opts[:title]
|
||||||
# If we're moving to a new topic...
|
|
||||||
Topic.transaction do
|
|
||||||
topic = Topic.create(user: moved_by, title: opts[:title], category: category)
|
|
||||||
first_post_number = move_posts_to_topic(moved_by, post_ids, topic)
|
|
||||||
end
|
|
||||||
|
|
||||||
elsif opts[:destination_topic_id].present?
|
|
||||||
# If we're moving to an existing topic...
|
|
||||||
|
|
||||||
topic = Topic.where(id: opts[:destination_topic_id]).first
|
|
||||||
Guardian.new(moved_by).ensure_can_see!(topic)
|
|
||||||
first_post_number = move_posts_to_topic(moved_by, post_ids, topic)
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Add a moderator post explaining that the post was moved
|
|
||||||
if topic.present?
|
|
||||||
topic_url = "#{Discourse.base_url}#{topic.relative_url}"
|
|
||||||
topic_link = "[#{topic.title}](#{topic_url})"
|
|
||||||
|
|
||||||
add_moderator_post(moved_by, I18n.t("move_posts.moderator_post", count: post_ids.size, topic_link: topic_link), post_number: first_post_number)
|
|
||||||
Jobs.enqueue(:notify_moved_posts, post_ids: post_ids, moved_by_id: moved_by.id)
|
|
||||||
|
|
||||||
topic.update_statistics
|
|
||||||
update_statistics
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
topic
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Updates the denormalized statistics of a topic including featured posters. They shouldn't
|
# Updates the denormalized statistics of a topic including featured posters. They shouldn't
|
||||||
|
|
Loading…
Reference in New Issue
Block a user