2019-05-03 06:17:27 +08:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2014-08-29 03:09:36 +08:00
|
|
|
class Permalink < ActiveRecord::Base
|
|
|
|
belongs_to :topic
|
|
|
|
belongs_to :post
|
|
|
|
belongs_to :category
|
2020-05-25 17:48:54 +08:00
|
|
|
belongs_to :tag
|
2024-02-06 00:31:31 +08:00
|
|
|
belongs_to :user
|
2014-08-29 03:09:36 +08:00
|
|
|
|
2024-05-28 04:33:30 +08:00
|
|
|
before_validation :normalize_url, :encode_url
|
2014-08-29 03:09:36 +08:00
|
|
|
|
2021-03-30 02:36:59 +08:00
|
|
|
validates :url, uniqueness: true
|
|
|
|
|
2015-07-15 13:32:35 +08:00
|
|
|
class Normalizer
|
|
|
|
attr_reader :source
|
|
|
|
|
|
|
|
def initialize(source)
|
|
|
|
@source = source
|
|
|
|
@rules = source.split("|").map { |rule| parse_rule(rule) }.compact if source.present?
|
|
|
|
end
|
|
|
|
|
|
|
|
def parse_rule(rule)
|
|
|
|
return unless rule =~ %r{/.*/}
|
|
|
|
|
|
|
|
escaping = false
|
2019-05-03 06:17:27 +08:00
|
|
|
regex = +""
|
|
|
|
sub = +""
|
2015-07-15 13:32:35 +08:00
|
|
|
c = 0
|
|
|
|
|
|
|
|
rule.chars.each do |l|
|
|
|
|
c += 1 if !escaping && l == "/"
|
|
|
|
escaping = l == "\\"
|
|
|
|
|
|
|
|
if c > 1
|
|
|
|
sub << l
|
|
|
|
else
|
|
|
|
regex << l
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-03-28 16:20:08 +08:00
|
|
|
[Regexp.new(regex[1..-1]), sub[1..-1] || ""] if regex.length > 1
|
2015-07-15 13:32:35 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
def normalize(url)
|
|
|
|
return url unless @rules
|
|
|
|
@rules.each { |(regex, sub)| url = url.sub(regex, sub) }
|
|
|
|
|
|
|
|
url
|
2014-08-29 03:09:36 +08:00
|
|
|
end
|
2015-07-15 13:32:35 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
def self.normalize_url(url)
|
|
|
|
if url
|
|
|
|
url = url.strip
|
|
|
|
url = url[1..-1] if url[0, 1] == "/"
|
|
|
|
end
|
|
|
|
|
|
|
|
normalizations = SiteSetting.permalink_normalizations
|
|
|
|
|
|
|
|
@normalizer = Normalizer.new(normalizations) unless @normalizer &&
|
|
|
|
@normalizer.source == normalizations
|
|
|
|
@normalizer.normalize(url)
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.find_by_url(url)
|
|
|
|
find_by(url: normalize_url(url))
|
|
|
|
end
|
|
|
|
|
2014-08-29 03:09:36 +08:00
|
|
|
def target_url
|
2024-05-28 03:31:51 +08:00
|
|
|
return relative_external_url if external_url
|
2024-05-28 03:30:19 +08:00
|
|
|
return post.relative_url if post
|
2014-08-29 03:09:36 +08:00
|
|
|
return topic.relative_url if topic
|
2024-05-28 03:30:19 +08:00
|
|
|
return category.relative_url if category
|
|
|
|
return tag.relative_url if tag
|
|
|
|
return user.relative_url if user
|
2014-08-29 03:09:36 +08:00
|
|
|
nil
|
|
|
|
end
|
2015-07-17 18:23:48 +08:00
|
|
|
|
|
|
|
def self.filter_by(url = nil)
|
|
|
|
permalinks =
|
2024-02-06 00:31:31 +08:00
|
|
|
Permalink.includes(:topic, :post, :category, :tag, :user).order("permalinks.created_at desc")
|
2015-07-17 18:23:48 +08:00
|
|
|
|
|
|
|
permalinks.where!("url ILIKE :url OR external_url ILIKE :url", url: "%#{url}%") if url.present?
|
|
|
|
permalinks.limit!(100)
|
|
|
|
permalinks.to_a
|
|
|
|
end
|
2024-05-28 04:33:30 +08:00
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
def normalize_url
|
|
|
|
self.url = Permalink.normalize_url(url) if url
|
|
|
|
end
|
|
|
|
|
|
|
|
def encode_url
|
|
|
|
self.url = UrlHelper.encode(url) if url
|
|
|
|
end
|
|
|
|
|
|
|
|
def relative_external_url
|
|
|
|
external_url.match?(%r{\A/[^/]}) ? "#{Discourse.base_path}#{external_url}" : external_url
|
|
|
|
end
|
2014-08-29 03:09:36 +08:00
|
|
|
end
|
2014-10-08 23:50:44 +08:00
|
|
|
|
|
|
|
# == Schema Information
|
|
|
|
#
|
|
|
|
# Table name: permalinks
|
|
|
|
#
|
|
|
|
# id :integer not null, primary key
|
|
|
|
# url :string(1000) not null
|
|
|
|
# topic_id :integer
|
|
|
|
# post_id :integer
|
|
|
|
# category_id :integer
|
2019-01-12 03:29:56 +08:00
|
|
|
# created_at :datetime not null
|
|
|
|
# updated_at :datetime not null
|
2014-10-08 23:50:44 +08:00
|
|
|
# external_url :string(1000)
|
2020-05-25 17:48:54 +08:00
|
|
|
# tag_id :integer
|
2024-02-06 00:31:31 +08:00
|
|
|
# user_id :integer
|
2014-10-08 23:50:44 +08:00
|
|
|
#
|
|
|
|
# Indexes
|
|
|
|
#
|
|
|
|
# index_permalinks_on_url (url) UNIQUE
|
|
|
|
#
|