2019-05-03 06:17:27 +08:00
# frozen_string_literal: true
2013-02-06 03:16:51 +08:00
# A class we can use to serialize the site data
class Site
include ActiveModel :: Serialization
2019-03-16 19:48:57 +08:00
cattr_accessor :preloaded_category_custom_fields
2022-07-14 08:54:31 +08:00
def self . reset_preloaded_category_custom_fields
self . preloaded_category_custom_fields = Set . new
end
reset_preloaded_category_custom_fields
2019-03-16 19:48:57 +08:00
2022-01-28 11:02:02 +08:00
##
# Sometimes plugins need to have additional data or options available
# when rendering custom markdown features/rules that are not available
# on the default opts.discourse object. These additional options should
# be namespaced to the plugin adding them.
#
# ```
# Site.markdown_additional_options["chat"] = { limited_pretty_text_markdown_rules: [] }
# ```
#
# These are passed down to markdown rules on opts.discourse.additionalOptions.
cattr_accessor :markdown_additional_options
self . markdown_additional_options = { }
2021-07-19 13:54:19 +08:00
def self . add_categories_callbacks ( & block )
categories_callbacks << block
end
def self . categories_callbacks
@categories_callbacks || = [ ]
end
2013-05-13 16:04:03 +08:00
def initialize ( guardian )
@guardian = guardian
end
2013-02-06 03:16:51 +08:00
def site_setting
SiteSetting
end
def notification_types
2013-03-01 20:07:44 +08:00
Notification . types
2013-02-06 03:16:51 +08:00
end
def trust_levels
2021-06-02 04:11:48 +08:00
TrustLevel . levels
2013-02-06 03:16:51 +08:00
end
2013-02-07 23:45:24 +08:00
2014-09-27 02:48:34 +08:00
def user_fields
2021-10-29 02:28:31 +08:00
UserField . includes ( :user_field_options ) . order ( :position ) . all
2014-09-27 02:48:34 +08:00
end
2021-07-22 15:18:18 +08:00
def self . categories_cache_key
" site_categories_ #{ Discourse . git_version } "
end
2021-06-23 15:21:11 +08:00
def self . clear_cache
2021-07-22 15:18:18 +08:00
Discourse . cache . delete ( categories_cache_key )
2021-06-23 15:21:11 +08:00
end
def self . all_categories_cache
# Categories do not change often so there is no need for us to run the
# same query and spend time creating ActiveRecord objects for every requests.
#
# Do note that any new association added to the eager loading needs a
# corresponding ActiveRecord callback to clear the categories cache.
2021-07-22 15:18:18 +08:00
Discourse . cache . fetch ( categories_cache_key , expires_in : 30 . minutes ) do
2013-07-16 13:44:07 +08:00
categories = Category
2022-04-06 21:08:06 +08:00
. includes ( :uploaded_logo , :uploaded_background , :tags , :tag_groups , category_required_tag_groups : :tag_group )
2015-09-28 14:49:39 +08:00
. joins ( 'LEFT JOIN topics t on t.id = categories.topic_id' )
2015-09-28 14:43:38 +08:00
. select ( 'categories.*, t.slug topic_slug' )
2013-11-07 05:56:49 +08:00
. order ( :position )
2021-06-23 15:21:11 +08:00
. to_a
if preloaded_category_custom_fields . present?
Category . preload_custom_fields (
categories ,
preloaded_category_custom_fields
)
end
2015-02-20 14:30:31 +08:00
2021-06-23 15:21:11 +08:00
ActiveModel :: ArraySerializer . new (
categories ,
each_serializer : SiteCategorySerializer
) . as_json
end
end
def categories
@categories || = begin
categories = [ ]
self . class . all_categories_cache . each do | category |
if @guardian . can_see_serialized_category? ( category_id : category [ :id ] , read_restricted : category [ :read_restricted ] )
2021-06-28 10:39:13 +08:00
categories << category
2021-06-23 15:21:11 +08:00
end
end
2013-07-16 13:44:07 +08:00
2015-09-23 11:13:34 +08:00
with_children = Set . new
categories . each do | c |
2021-06-28 10:39:13 +08:00
if c [ :parent_category_id ]
with_children << c [ :parent_category_id ]
2015-09-23 11:13:34 +08:00
end
end
2017-05-12 23:09:28 +08:00
allowed_topic_create = nil
unless @guardian . is_admin?
allowed_topic_create_ids =
@guardian . anonymous? ? [ ] : Category . topic_create_allowed ( @guardian ) . pluck ( :id )
allowed_topic_create = Set . new ( allowed_topic_create_ids )
end
2013-07-16 13:44:07 +08:00
2014-02-25 03:52:21 +08:00
by_id = { }
2014-04-17 17:17:39 +08:00
2021-05-14 07:45:14 +08:00
notification_levels = CategoryUser . notification_levels_for ( @guardian . user )
2019-11-08 10:58:11 +08:00
default_notification_level = CategoryUser . default_notification_level
2015-12-20 14:47:02 +08:00
2014-06-18 09:21:53 +08:00
categories . each do | category |
2021-06-28 10:39:13 +08:00
category [ :notification_level ] = notification_levels [ category [ :id ] ] || default_notification_level
category [ :permission ] = CategoryGroup . permission_types [ :full ] if allowed_topic_create & . include? ( category [ :id ] ) || @guardian . is_admin?
category [ :has_children ] = with_children . include? ( category [ :id ] )
category [ :can_edit ] = @guardian . can_edit_serialized_category? (
category_id : category [ :id ] ,
read_restricted : category [ :read_restricted ]
)
by_id [ category [ :id ] ] = category
2013-07-16 13:44:07 +08:00
end
2014-02-25 03:52:21 +08:00
2021-06-28 10:39:13 +08:00
categories . reject! { | c | c [ :parent_category_id ] && ! by_id [ c [ :parent_category_id ] ] }
2021-07-19 13:54:19 +08:00
self . class . categories_callbacks . each do | callback |
callback . call ( categories )
end
2013-07-16 13:44:07 +08:00
categories
end
2013-02-07 23:45:24 +08:00
end
2013-02-06 03:16:51 +08:00
2019-02-14 22:35:58 +08:00
def groups
2021-09-17 10:34:04 +08:00
Group
. visible_groups ( @guardian . user , " name ASC " , include_everyone : true )
. includes ( :flair_upload )
2019-02-14 22:35:58 +08:00
end
2013-02-06 03:16:51 +08:00
def archetypes
2013-03-01 02:54:12 +08:00
Archetype . list . reject { | t | t . id == Archetype . private_message }
2013-02-06 03:16:51 +08:00
end
2018-07-31 23:18:50 +08:00
def auth_providers
Discourse . enabled_auth_providers
end
2014-02-25 03:24:18 +08:00
def self . json_for ( guardian )
2013-10-15 06:50:30 +08:00
if guardian . anonymous? && SiteSetting . login_required
2014-01-20 21:41:11 +08:00
return {
periods : TopTopic . periods . map ( & :to_s ) ,
filters : Discourse . filters . map ( & :to_s ) ,
2021-10-29 02:28:31 +08:00
user_fields : UserField . includes ( :user_field_options ) . order ( :position ) . all . map do | userfield |
2015-08-18 03:44:08 +08:00
UserFieldSerializer . new ( userfield , root : false , scope : guardian )
2018-08-07 16:20:09 +08:00
end ,
auth_providers : Discourse . enabled_auth_providers . map do | provider |
AuthProviderSerializer . new ( provider , root : false , scope : guardian )
2017-09-07 21:15:29 +08:00
end
2014-01-20 21:41:11 +08:00
} . to_json
2013-10-15 06:50:30 +08:00
end
2015-09-28 14:44:03 +08:00
seq = nil
if guardian . anonymous?
seq = MessageBus . last_id ( '/site_json' )
2019-12-03 17:05:53 +08:00
cached_json , cached_seq , cached_version = Discourse . redis . mget ( 'site_json' , 'site_json_seq' , 'site_json_version' )
2015-09-28 14:44:03 +08:00
if cached_json && seq == cached_seq . to_i && Discourse . git_version == cached_version
return cached_json
end
end
2013-05-13 16:04:03 +08:00
site = Site . new ( guardian )
2015-09-28 14:44:03 +08:00
json = MultiJson . dump ( SiteSerializer . new ( site , root : false , scope : guardian ) )
if guardian . anonymous?
2022-05-10 06:19:02 +08:00
Discourse . redis . multi do | transaction |
transaction . setex 'site_json' , 1800 , json
transaction . set 'site_json_seq' , seq
transaction . set 'site_json_version' , Discourse . git_version
2015-09-28 14:44:03 +08:00
end
end
json
end
2018-12-17 17:27:44 +08:00
SITE_JSON_CHANNEL = '/site_json'
2015-09-28 14:44:03 +08:00
def self . clear_anon_cache!
# publishing forces the sequence up
# the cache is validated based on the sequence
2018-12-17 17:27:44 +08:00
MessageBus . publish ( SITE_JSON_CHANNEL , '' )
2013-02-06 03:16:51 +08:00
end
2022-08-10 00:22:39 +08:00
def self . show_welcome_topic_banner? ( guardian )
return false unless guardian . is_admin?
return false unless guardian . user . id == User . first_login_admin_id
Post . find_by ( " topic_id = :topic_id AND post_number = 1 AND version = 1 AND created_at > :created_at " , topic_id : SiteSetting . welcome_topic_id , created_at : 1 . month . ago ) . present?
end
2013-02-06 03:16:51 +08:00
end