mirror of
https://github.com/discourse/discourse.git
synced 2024-11-25 06:30:15 +08:00
728e8a262c
Due to what seems to be a bug in ActiveRecord, the distinct: true option is not recognized on counts with string column names. This commit fixes that by moving the DISTINCT into the count string. For robustness, the integration spec for IncomingLinksReport was rewritten to be an actual integration spec, running the actual interface on actual fake data.
119 lines
3.8 KiB
Ruby
119 lines
3.8 KiB
Ruby
class IncomingLinksReport
|
|
|
|
attr_accessor :type, :data, :y_titles
|
|
|
|
def initialize(type)
|
|
@type = type
|
|
@y_titles = {}
|
|
@data = nil
|
|
end
|
|
|
|
def as_json(_options = nil)
|
|
{
|
|
type: self.type,
|
|
title: I18n.t("reports.#{self.type}.title"),
|
|
xaxis: I18n.t("reports.#{self.type}.xaxis"),
|
|
ytitles: self.y_titles,
|
|
data: self.data
|
|
}
|
|
end
|
|
|
|
def self.find(type, _opts = {})
|
|
report_method = :"report_#{type}"
|
|
return nil unless respond_to?(report_method)
|
|
|
|
# Load the report
|
|
report = IncomingLinksReport.new(type)
|
|
send(report_method, report)
|
|
report
|
|
end
|
|
|
|
# Return top 10 users who brought traffic to the site within the last 30 days
|
|
def self.report_top_referrers(report)
|
|
report.y_titles[:num_clicks] = I18n.t("reports.#{report.type}.num_clicks")
|
|
report.y_titles[:num_topics] = I18n.t("reports.#{report.type}.num_topics")
|
|
|
|
num_clicks = link_count_per_user
|
|
num_topics = topic_count_per_user
|
|
report.data = []
|
|
num_clicks.keys.each do |username|
|
|
report.data << {username: username, num_clicks: num_clicks[username], num_topics: num_topics[username]}
|
|
end
|
|
report.data = report.data.sort_by {|x| x[:num_clicks]}.reverse[0,10]
|
|
end
|
|
|
|
def self.per_user
|
|
@per_user_query ||= IncomingLink
|
|
.where('incoming_links.created_at > ? AND incoming_links.user_id IS NOT NULL', 30.days.ago)
|
|
.joins(:user)
|
|
.group('users.username')
|
|
end
|
|
|
|
def self.link_count_per_user
|
|
per_user.count
|
|
end
|
|
|
|
def self.topic_count_per_user
|
|
per_user.joins(:post).count("DISTINCT posts.topic_id")
|
|
end
|
|
|
|
|
|
# Return top 10 domains that brought traffic to the site within the last 30 days
|
|
def self.report_top_traffic_sources(report)
|
|
report.y_titles[:num_clicks] = I18n.t("reports.#{report.type}.num_clicks")
|
|
report.y_titles[:num_topics] = I18n.t("reports.#{report.type}.num_topics")
|
|
report.y_titles[:num_users] = I18n.t("reports.#{report.type}.num_users")
|
|
|
|
num_clicks = link_count_per_domain
|
|
num_topics = topic_count_per_domain(num_clicks.keys)
|
|
report.data = []
|
|
num_clicks.keys.each do |domain|
|
|
report.data << {domain: domain, num_clicks: num_clicks[domain], num_topics: num_topics[domain]}
|
|
end
|
|
report.data = report.data.sort_by {|x| x[:num_clicks]}.reverse[0,10]
|
|
end
|
|
|
|
def self.link_count_per_domain(limit=10)
|
|
IncomingLink.where('incoming_links.created_at > ?', 30.days.ago)
|
|
.joins(:incoming_referer => :incoming_domain)
|
|
.group('incoming_domains.name')
|
|
.order('count_all DESC')
|
|
.limit(limit).count
|
|
end
|
|
|
|
def self.per_domain(domains)
|
|
IncomingLink
|
|
.joins(:incoming_referer => :incoming_domain)
|
|
.where('incoming_links.created_at > ? AND incoming_domains.name IN (?)', 30.days.ago, domains)
|
|
.group('incoming_domains.name')
|
|
end
|
|
|
|
def self.topic_count_per_domain(domains)
|
|
# COUNT(DISTINCT) is slow
|
|
per_domain(domains).joins(:post).count("DISTINCT posts.topic_id")
|
|
end
|
|
|
|
|
|
def self.report_top_referred_topics(report)
|
|
report.y_titles[:num_clicks] = I18n.t("reports.#{report.type}.num_clicks")
|
|
num_clicks = link_count_per_topic
|
|
num_clicks = num_clicks.to_a.sort_by {|x| x[1]}.last(10).reverse # take the top 10
|
|
report.data = []
|
|
topics = Topic.select('id, slug, title').where('id in (?)', num_clicks.map {|z| z[0]})
|
|
num_clicks.each do |topic_id, num_clicks_element|
|
|
topic = topics.find {|t| t.id == topic_id}
|
|
if topic
|
|
report.data << {topic_id: topic_id, topic_title: topic.title, topic_slug: topic.slug, num_clicks: num_clicks_element}
|
|
end
|
|
end
|
|
report.data
|
|
end
|
|
|
|
def self.link_count_per_topic
|
|
IncomingLink.joins(:post)
|
|
.where('incoming_links.created_at > ? AND topic_id IS NOT NULL', 30.days.ago)
|
|
.group('topic_id')
|
|
.count
|
|
end
|
|
end
|