REFACTOR: split `TopicLink#extract_from` into multiple methods
Also rename some confusing variables
This commit is contained in:
parent
37249c9a32
commit
a1d9aeda8b
|
@ -111,7 +111,7 @@ SQL
|
|||
def self.extract_from(post)
|
||||
return if post.blank? || post.whisper?
|
||||
|
||||
added_urls = []
|
||||
current_urls = []
|
||||
reflected_ids = []
|
||||
|
||||
PrettyText
|
||||
|
@ -130,93 +130,9 @@ SQL
|
|||
|
||||
TopicLink.transaction do
|
||||
begin
|
||||
url = link.url
|
||||
internal = false
|
||||
topic_id = nil
|
||||
post_number = nil
|
||||
|
||||
if upload = Upload.get_from_url(url)
|
||||
internal = Discourse.store.internal?
|
||||
# Store the same URL that will be used in the cooked version of the post
|
||||
url = UrlHelper.cook_url(upload.url)
|
||||
elsif route = Discourse.route_for(parsed)
|
||||
internal = true
|
||||
|
||||
# We aren't interested in tracking internal links to users
|
||||
next if route[:controller] == 'users'
|
||||
|
||||
topic_id = route[:topic_id].to_i
|
||||
post_number = route[:post_number] || 1
|
||||
|
||||
# Store the canonical URL
|
||||
topic = Topic.find_by(id: topic_id)
|
||||
topic_id = nil unless topic
|
||||
|
||||
if topic.present?
|
||||
url = "#{Discourse.base_url_no_prefix}#{topic.relative_url}"
|
||||
url << "/#{post_number}" if post_number.to_i > 1
|
||||
end
|
||||
end
|
||||
|
||||
# Skip linking to ourselves
|
||||
next if topic_id == post.topic_id
|
||||
|
||||
reflected_post = nil
|
||||
if post_number && topic_id
|
||||
reflected_post = Post.find_by(topic_id: topic_id, post_number: post_number.to_i)
|
||||
end
|
||||
|
||||
url = url[0...TopicLink.max_url_length]
|
||||
next if parsed && parsed.host && parsed.host.length > TopicLink.max_domain_length
|
||||
|
||||
added_urls << url
|
||||
|
||||
unless TopicLink.exists?(topic_id: post.topic_id, post_id: post.id, url: url)
|
||||
file_extension = File.extname(parsed.path)[1..10].downcase unless parsed.path.nil? || File.extname(parsed.path).empty?
|
||||
begin
|
||||
TopicLink.create!(post_id: post.id,
|
||||
user_id: post.user_id,
|
||||
topic_id: post.topic_id,
|
||||
url: url,
|
||||
domain: parsed.host || Discourse.current_hostname,
|
||||
internal: internal,
|
||||
link_topic_id: topic_id,
|
||||
link_post_id: reflected_post.try(:id),
|
||||
quote: link.is_quote,
|
||||
extension: file_extension)
|
||||
rescue ActiveRecord::RecordNotUnique
|
||||
# it's fine
|
||||
end
|
||||
end
|
||||
|
||||
# Create the reflection if we can
|
||||
if topic_id.present?
|
||||
topic = Topic.find_by(id: topic_id)
|
||||
|
||||
if topic && post.topic && topic.archetype != 'private_message' && post.topic.archetype != 'private_message' && post.topic.visible?
|
||||
prefix = Discourse.base_url_no_prefix
|
||||
reflected_url = "#{prefix}#{post.topic.relative_url(post.post_number)}"
|
||||
tl = TopicLink.find_by(topic_id: topic_id,
|
||||
post_id: reflected_post.try(:id),
|
||||
url: reflected_url)
|
||||
|
||||
unless tl
|
||||
tl = TopicLink.create(user_id: post.user_id,
|
||||
topic_id: topic_id,
|
||||
post_id: reflected_post.try(:id),
|
||||
url: reflected_url,
|
||||
domain: Discourse.current_hostname,
|
||||
reflection: true,
|
||||
internal: true,
|
||||
link_topic_id: post.topic_id,
|
||||
link_post_id: post.id)
|
||||
|
||||
end
|
||||
|
||||
reflected_ids << tl.id if tl.persisted?
|
||||
end
|
||||
end
|
||||
|
||||
url, reflected_id = self.ensure_entry_for(post, link, parsed)
|
||||
current_urls << url unless url.nil?
|
||||
reflected_ids << reflected_id unless reflected_id.nil?
|
||||
rescue URI::Error
|
||||
# if the URI is invalid, don't store it.
|
||||
rescue ActionController::RoutingError
|
||||
|
@ -225,32 +141,7 @@ SQL
|
|||
end
|
||||
end
|
||||
|
||||
# Remove links that aren't there anymore
|
||||
if added_urls.present?
|
||||
TopicLink.where(
|
||||
"(url not in (:urls)) AND (post_id = :post_id AND NOT reflection)",
|
||||
urls: added_urls, post_id: post.id
|
||||
).delete_all
|
||||
|
||||
reflected_ids.compact!
|
||||
if reflected_ids.present?
|
||||
TopicLink.where(
|
||||
"(id not in (:reflected_ids)) AND (link_post_id = :post_id AND reflection)",
|
||||
reflected_ids: reflected_ids, post_id: post.id
|
||||
).delete_all
|
||||
else
|
||||
TopicLink
|
||||
.where("link_post_id = :post_id AND reflection", post_id: post.id)
|
||||
.delete_all
|
||||
end
|
||||
else
|
||||
TopicLink
|
||||
.where(
|
||||
"(post_id = :post_id AND NOT reflection) OR (link_post_id = :post_id AND reflection)",
|
||||
post_id: post.id
|
||||
)
|
||||
.delete_all
|
||||
end
|
||||
self.cleanup_entries(post, current_urls, reflected_ids)
|
||||
|
||||
end
|
||||
|
||||
|
@ -278,6 +169,128 @@ SQL
|
|||
|
||||
lookup
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def self.ensure_entry_for(post, link, parsed)
|
||||
url = link.url
|
||||
internal = false
|
||||
topic_id = nil
|
||||
post_number = nil
|
||||
|
||||
if upload = Upload.get_from_url(url)
|
||||
internal = Discourse.store.internal?
|
||||
# Store the same URL that will be used in the cooked version of the post
|
||||
url = UrlHelper.cook_url(upload.url)
|
||||
elsif route = Discourse.route_for(parsed)
|
||||
internal = true
|
||||
|
||||
# We aren't interested in tracking internal links to users
|
||||
return nil if route[:controller] == 'users'
|
||||
|
||||
topic_id = route[:topic_id].to_i
|
||||
post_number = route[:post_number] || 1
|
||||
|
||||
# Store the canonical URL
|
||||
topic = Topic.find_by(id: topic_id)
|
||||
topic_id = nil unless topic
|
||||
|
||||
if topic.present?
|
||||
url = "#{Discourse.base_url_no_prefix}#{topic.relative_url}"
|
||||
url << "/#{post_number}" if post_number.to_i > 1
|
||||
end
|
||||
end
|
||||
|
||||
# Skip linking to ourselves
|
||||
return nil if topic_id == post.topic_id
|
||||
|
||||
reflected_post = nil
|
||||
if post_number && topic_id
|
||||
reflected_post = Post.find_by(topic_id: topic_id, post_number: post_number.to_i)
|
||||
end
|
||||
|
||||
url = url[0...TopicLink.max_url_length]
|
||||
return nil if parsed && parsed.host && parsed.host.length > TopicLink.max_domain_length
|
||||
|
||||
unless TopicLink.exists?(topic_id: post.topic_id, post_id: post.id, url: url)
|
||||
file_extension = File.extname(parsed.path)[1..10].downcase unless parsed.path.nil? || File.extname(parsed.path).empty?
|
||||
begin
|
||||
TopicLink.create!(post_id: post.id,
|
||||
user_id: post.user_id,
|
||||
topic_id: post.topic_id,
|
||||
url: url,
|
||||
domain: parsed.host || Discourse.current_hostname,
|
||||
internal: internal,
|
||||
link_topic_id: topic_id,
|
||||
link_post_id: reflected_post.try(:id),
|
||||
quote: link.is_quote,
|
||||
extension: file_extension)
|
||||
rescue ActiveRecord::RecordNotUnique
|
||||
# it's fine
|
||||
end
|
||||
end
|
||||
|
||||
reflected_id = nil
|
||||
|
||||
# Create the reflection if we can
|
||||
if topic_id.present?
|
||||
topic = Topic.find_by(id: topic_id)
|
||||
|
||||
if topic && post.topic && topic.archetype != 'private_message' && post.topic.archetype != 'private_message' && post.topic.visible?
|
||||
prefix = Discourse.base_url_no_prefix
|
||||
reflected_url = "#{prefix}#{post.topic.relative_url(post.post_number)}"
|
||||
tl = TopicLink.find_by(topic_id: topic_id,
|
||||
post_id: reflected_post.try(:id),
|
||||
url: reflected_url)
|
||||
|
||||
unless tl
|
||||
tl = TopicLink.create(user_id: post.user_id,
|
||||
topic_id: topic_id,
|
||||
post_id: reflected_post.try(:id),
|
||||
url: reflected_url,
|
||||
domain: Discourse.current_hostname,
|
||||
reflection: true,
|
||||
internal: true,
|
||||
link_topic_id: post.topic_id,
|
||||
link_post_id: post.id)
|
||||
|
||||
end
|
||||
|
||||
reflected_id = tl.id if tl.persisted?
|
||||
end
|
||||
end
|
||||
|
||||
[url, reflected_id]
|
||||
end
|
||||
|
||||
def self.cleanup_entries(post, current_urls, current_reflected_ids)
|
||||
# Remove links that aren't there anymore
|
||||
if current_urls.present?
|
||||
TopicLink.where(
|
||||
"(url not in (:urls)) AND (post_id = :post_id AND NOT reflection)",
|
||||
urls: current_urls, post_id: post.id
|
||||
).delete_all
|
||||
|
||||
current_reflected_ids.compact!
|
||||
if current_reflected_ids.present?
|
||||
TopicLink.where(
|
||||
"(id not in (:reflected_ids)) AND (link_post_id = :post_id AND reflection)",
|
||||
reflected_ids: current_reflected_ids, post_id: post.id
|
||||
).delete_all
|
||||
else
|
||||
TopicLink
|
||||
.where("link_post_id = :post_id AND reflection", post_id: post.id)
|
||||
.delete_all
|
||||
end
|
||||
else
|
||||
TopicLink
|
||||
.where(
|
||||
"(post_id = :post_id AND NOT reflection) OR (link_post_id = :post_id AND reflection)",
|
||||
post_id: post.id
|
||||
)
|
||||
.delete_all
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# == Schema Information
|
||||
|
|
Loading…
Reference in New Issue