# frozen_string_literal: true class About class CategoryMods include ActiveModel::Serialization attr_reader :category, :moderators def initialize(category, moderators) @category = category @moderators = moderators end def parent_category category.parent_category end end include ActiveModel::Serialization include StatsCacheable def self.stats_cache_key "about-stats" end def self.fetch_stats Stat.api_stats end def initialize(user = nil) @user = user end def version Discourse::VERSION::STRING end def https SiteSetting.force_https end def title SiteSetting.title end def locale SiteSetting.default_locale end def description SiteSetting.site_description end def extended_site_description SiteSetting.extended_site_description_cooked end def banner_image url = SiteSetting.about_banner_image&.url return if url.blank? GlobalPath.full_cdn_url(url) end def site_creation_date Discourse.site_creation_date end def moderators @moderators ||= apply_excluded_groups( User.where(moderator: true, admin: false).human_users.order(last_seen_at: :desc), ) end def admins @admins ||= DiscoursePluginRegistry.apply_modifier( :about_admins, apply_excluded_groups(User.where(admin: true).human_users.order(last_seen_at: :desc)), ) end def stats @stats ||= About.fetch_cached_stats end def category_moderators allowed_cats = Guardian.new(@user).allowed_category_ids return [] if allowed_cats.blank? cats_with_mods = Category.joins(:category_moderation_groups).distinct.pluck(:id) category_ids = cats_with_mods & allowed_cats return [] if category_ids.blank? per_cat_limit = category_mods_limit / category_ids.size per_cat_limit = 1 if per_cat_limit < 1 results = DB.query(<<~SQL, category_ids:) WITH moderator_users AS ( SELECT cmg.category_id AS category_id, u.id AS user_id, u.last_seen_at, ROW_NUMBER() OVER (PARTITION BY cmg.category_id, u.id ORDER BY u.last_seen_at DESC) as rn FROM category_moderation_groups cmg INNER JOIN group_users gu ON cmg.group_id = gu.group_id INNER JOIN users u ON gu.user_id = u.id WHERE cmg.category_id IN (:category_ids) ) SELECT id AS category_id, user_ids FROM categories INNER JOIN ( SELECT category_id, (ARRAY_AGG(user_id ORDER BY last_seen_at DESC))[:#{per_cat_limit}] AS user_ids FROM moderator_users WHERE rn = 1 GROUP BY category_id ) X ON X.category_id = id ORDER BY position SQL cats = Category.where(id: results.map(&:category_id)).index_by(&:id) mods = User.where(id: results.map(&:user_ids).flatten.uniq).index_by(&:id) results.map { |row| CategoryMods.new(cats[row.category_id], mods.values_at(*row.user_ids)) } end def category_mods_limit @category_mods_limit || 100 end def category_mods_limit=(number) @category_mods_limit = number end private def apply_excluded_groups(query) group_ids = SiteSetting.about_page_hidden_groups_map return query if group_ids.blank? query.joins( DB.sql_fragment( "LEFT JOIN group_users ON group_id IN (:group_ids) AND user_id = users.id", group_ids:, ), ).where("group_users.id": nil) end end