REFACTOR: split `TopicLink#extract_from` into multiple methods

Also rename some confusing variables
This commit is contained in:
David Taylor 2018-12-05 17:21:50 +00:00 committed by Régis Hanol
parent 37249c9a32
commit a1d9aeda8b
1 changed files with 127 additions and 114 deletions

View File

@ -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