2019-05-02 17:17:27 -05:00
# frozen_string_literal: true
2013-02-05 13:16:51 -06:00
# A class we can use to serialize the site data
class Site
include ActiveModel :: Serialization
2019-03-16 06:48:57 -05:00
cattr_accessor :preloaded_category_custom_fields
2022-07-13 19:54:31 -05:00
def self . reset_preloaded_category_custom_fields
self . preloaded_category_custom_fields = Set . new
end
reset_preloaded_category_custom_fields
2019-03-16 06:48:57 -05:00
2022-01-27 21:02:02 -06: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 00:54:19 -05:00
def self . add_categories_callbacks ( & block )
categories_callbacks << block
end
def self . categories_callbacks
@categories_callbacks || = [ ]
end
2013-05-13 03:04:03 -05:00
def initialize ( guardian )
@guardian = guardian
end
2013-02-05 13:16:51 -06:00
def site_setting
SiteSetting
end
def notification_types
2013-03-01 06:07:44 -06:00
Notification . types
2013-02-05 13:16:51 -06:00
end
def trust_levels
2021-06-01 15:11:48 -05:00
TrustLevel . levels
2013-02-05 13:16:51 -06:00
end
2013-02-07 09:45:24 -06:00
2014-09-26 13:48:34 -05:00
def user_fields
2021-10-28 13:28:31 -05:00
UserField . includes ( :user_field_options ) . order ( :position ) . all
2014-09-26 13:48:34 -05:00
end
2021-07-22 02:18:18 -05:00
def self . categories_cache_key
" site_categories_ #{ Discourse . git_version } "
end
2021-06-23 02:21:11 -05:00
def self . clear_cache
2021-07-22 02:18:18 -05:00
Discourse . cache . delete ( categories_cache_key )
2021-06-23 02:21:11 -05: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 02:18:18 -05:00
Discourse . cache . fetch ( categories_cache_key , expires_in : 30 . minutes ) do
2013-07-16 00:44:07 -05:00
categories = Category
2022-04-06 08:08:06 -05:00
. includes ( :uploaded_logo , :uploaded_background , :tags , :tag_groups , category_required_tag_groups : :tag_group )
2015-09-28 01:49:39 -05:00
. joins ( 'LEFT JOIN topics t on t.id = categories.topic_id' )
2015-09-28 01:43:38 -05:00
. select ( 'categories.*, t.slug topic_slug' )
2013-11-06 15:56:49 -06:00
. order ( :position )
2021-06-23 02:21:11 -05:00
. to_a
if preloaded_category_custom_fields . present?
Category . preload_custom_fields (
categories ,
preloaded_category_custom_fields
)
end
2015-02-20 00:30:31 -06:00
2021-06-23 02:21:11 -05: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-27 21:39:13 -05:00
categories << category
2021-06-23 02:21:11 -05:00
end
end
2013-07-16 00:44:07 -05:00
2015-09-22 22:13:34 -05:00
with_children = Set . new
categories . each do | c |
2021-06-27 21:39:13 -05:00
if c [ :parent_category_id ]
with_children << c [ :parent_category_id ]
2015-09-22 22:13:34 -05:00
end
end
2017-05-12 10:09:28 -05: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 00:44:07 -05:00
2014-02-24 13:52:21 -06:00
by_id = { }
2014-04-17 04:17:39 -05:00
2021-05-13 18:45:14 -05:00
notification_levels = CategoryUser . notification_levels_for ( @guardian . user )
2019-11-07 20:58:11 -06:00
default_notification_level = CategoryUser . default_notification_level
2015-12-20 00:47:02 -06:00
2014-06-17 20:21:53 -05:00
categories . each do | category |
2021-06-27 21:39:13 -05: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 00:44:07 -05:00
end
2014-02-24 13:52:21 -06:00
2021-06-27 21:39:13 -05:00
categories . reject! { | c | c [ :parent_category_id ] && ! by_id [ c [ :parent_category_id ] ] }
2021-07-19 00:54:19 -05:00
self . class . categories_callbacks . each do | callback |
callback . call ( categories )
end
2013-07-16 00:44:07 -05:00
categories
end
2013-02-07 09:45:24 -06:00
end
2013-02-05 13:16:51 -06:00
2019-02-14 08:35:58 -06:00
def groups
2021-09-16 21:34:04 -05:00
Group
. visible_groups ( @guardian . user , " name ASC " , include_everyone : true )
. includes ( :flair_upload )
2019-02-14 08:35:58 -06:00
end
2013-02-05 13:16:51 -06:00
def archetypes
2013-02-28 12:54:12 -06:00
Archetype . list . reject { | t | t . id == Archetype . private_message }
2013-02-05 13:16:51 -06:00
end
2018-07-31 10:18:50 -05:00
def auth_providers
Discourse . enabled_auth_providers
end
2014-02-24 13:24:18 -06:00
def self . json_for ( guardian )
2013-10-14 17:50:30 -05:00
if guardian . anonymous? && SiteSetting . login_required
2014-01-20 07:41:11 -06:00
return {
periods : TopTopic . periods . map ( & :to_s ) ,
filters : Discourse . filters . map ( & :to_s ) ,
2021-10-28 13:28:31 -05:00
user_fields : UserField . includes ( :user_field_options ) . order ( :position ) . all . map do | userfield |
2015-08-17 14:44:08 -05:00
UserFieldSerializer . new ( userfield , root : false , scope : guardian )
2018-08-07 03:20:09 -05:00
end ,
auth_providers : Discourse . enabled_auth_providers . map do | provider |
AuthProviderSerializer . new ( provider , root : false , scope : guardian )
2017-09-07 08:15:29 -05:00
end
2014-01-20 07:41:11 -06:00
} . to_json
2013-10-14 17:50:30 -05:00
end
2015-09-28 01:44:03 -05:00
seq = nil
if guardian . anonymous?
seq = MessageBus . last_id ( '/site_json' )
2019-12-03 03:05:53 -06:00
cached_json , cached_seq , cached_version = Discourse . redis . mget ( 'site_json' , 'site_json_seq' , 'site_json_version' )
2015-09-28 01:44:03 -05:00
if cached_json && seq == cached_seq . to_i && Discourse . git_version == cached_version
return cached_json
end
end
2013-05-13 03:04:03 -05:00
site = Site . new ( guardian )
2015-09-28 01:44:03 -05:00
json = MultiJson . dump ( SiteSerializer . new ( site , root : false , scope : guardian ) )
if guardian . anonymous?
2022-05-09 17:19:02 -05: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 01:44:03 -05:00
end
end
json
end
2018-12-17 03:27:44 -06:00
SITE_JSON_CHANNEL = '/site_json'
2015-09-28 01:44:03 -05:00
def self . clear_anon_cache!
# publishing forces the sequence up
# the cache is validated based on the sequence
2018-12-17 03:27:44 -06:00
MessageBus . publish ( SITE_JSON_CHANNEL , '' )
2013-02-05 13:16:51 -06:00
end
2022-08-09 11:22:39 -05: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-05 13:16:51 -06:00
end