mirror of
https://github.com/discourse/discourse.git
synced 2026-08-09 21:45:25 +08:00
meta topic: [`/t/371843`](https://meta.discourse.org/t/nomethoderror-in-topicscontroller-show-error-after-merging-topics/371843) This fixes the bug pointed out about merging topics with events. The issue was that when merging topics with events, it circumvented the event validation logic and allowed event posts to be merged into topics that already have events or displace the event post in the destination. Add a topic extension to handle the event validation logic when merging topics with events. Also add null safety in the event serializer to handle cases where the event post is no longer valid.
50 lines
1.6 KiB
Ruby
Vendored
50 lines
1.6 KiB
Ruby
Vendored
# frozen_string_literal: true
|
|
|
|
module DiscoursePostEvent
|
|
module TopicExtension
|
|
def move_posts(moved_by, post_ids, opts)
|
|
ensure_event_invariants!(post_ids, opts)
|
|
super
|
|
end
|
|
|
|
private
|
|
|
|
def ensure_event_invariants!(post_ids, opts)
|
|
return unless SiteSetting.discourse_post_event_enabled
|
|
return unless opts[:destination_topic_id]
|
|
|
|
destination = Topic.find_by(id: opts[:destination_topic_id])
|
|
return unless destination
|
|
|
|
destination_op = destination.first_post
|
|
destination_has_event = destination_op&.event.present?
|
|
incoming_event_post = Post.where(id: post_ids).joins(:event).order(:created_at).first
|
|
|
|
return unless destination_has_event || incoming_event_post
|
|
|
|
raise_event_move_error! if destination_has_event && incoming_event_post
|
|
|
|
chronological = !!opts[:chronological_order]
|
|
|
|
if destination_has_event && chronological
|
|
oldest_incoming = Post.where(id: post_ids).order(:created_at).first
|
|
if oldest_incoming && oldest_incoming.created_at < destination_op.created_at
|
|
raise_event_move_error!
|
|
end
|
|
end
|
|
|
|
if incoming_event_post && !destination_has_event
|
|
becomes_new_op =
|
|
chronological &&
|
|
(destination_op.nil? || incoming_event_post.created_at < destination_op.created_at)
|
|
raise_event_move_error! unless becomes_new_op
|
|
end
|
|
end
|
|
|
|
def raise_event_move_error!
|
|
raise ActiveRecord::RecordNotSaved.new(
|
|
I18n.t("discourse_post_event.errors.models.event.must_be_in_first_post"),
|
|
)
|
|
end
|
|
end
|
|
end
|