2
0
Fork 0
mirror of https://github.com/discourse/discourse.git synced 2026-03-04 01:15:08 +08:00
discourse/app/models/theme_setting.rb
Isaac Janzen e5ea0fdb3d
DEV: Fix schema settings upload cleanup (#37063)
Problem: `Uploads` in objects type schema settings were being cleaned up
because `UploadReference` records weren't being created. The database
stores URLs, but `UploadReference.ensure_exist!` expects ids.

Fix: Modified the `after_save` hooks in both `SiteSetting` and
`ThemeSetting` to convert upload URLs to IDs before creating
`UploadReferences`.
2026-01-12 12:23:05 -06:00

104 lines
2.9 KiB
Ruby

# frozen_string_literal: true
class ThemeSetting < ActiveRecord::Base
belongs_to :theme
has_many :upload_references, as: :target, dependent: :destroy
TYPES_ENUM =
Enum.new(integer: 0, float: 1, string: 2, bool: 3, list: 4, enum: 5, upload: 6, objects: 7)
MAXIMUM_JSON_VALUE_SIZE_BYTES = 0.5 * 1024 * 1024 # 0.5 MB
validates :name, :theme, presence: true
validates :data_type, inclusion: { in: TYPES_ENUM.values }
validate :json_value_size, if: -> { self.data_type == TYPES_ENUM[:objects] }
validates :name, length: { maximum: 255 }
after_destroy :clear_settings_cache
after_save :clear_settings_cache
after_save do
if self.data_type == ThemeSetting.types[:upload] && saved_change_to_value?
UploadReference.ensure_exist!(upload_ids: [self.value], target: self)
elsif self.data_type == ThemeSetting.types[:objects] && saved_change_to_json_value? &&
self.json_value.present?
upload_values =
SchemaSettingsObjectValidator.property_values_of_type(
schema: theme.settings[self.name.to_sym].schema,
objects: self.json_value,
type: "upload",
)
# Convert URLs to upload IDs (values can be either integer IDs or URL strings)
upload_ids =
upload_values.filter_map do |value|
if value.is_a?(Integer)
value
elsif value.is_a?(String) && value.present?
Upload.get_from_url(value)&.id
end
end
# Always call ensure_exist! to clean up old references when uploads are removed
UploadReference.ensure_exist!(upload_ids: upload_ids, target: self)
end
if theme.theme_modifier_set.refresh_theme_setting_modifiers(
target_setting_name: self.name,
target_setting_value: self.value,
)
theme.theme_modifier_set.save!
end
end
def clear_settings_cache
# All necessary caches will be cleared on next ensure_baked!
theme.settings_field&.invalidate_baked!
end
def self.types
TYPES_ENUM
end
def self.guess_type(value)
case value
when Integer
types[:integer]
when Float
types[:float]
when String
types[:string]
when TrueClass, FalseClass
types[:bool]
end
end
private
def json_value_size
if json_value.to_json.size > MAXIMUM_JSON_VALUE_SIZE_BYTES
errors.add(
:json_value,
I18n.t(
"theme_settings.errors.json_value.too_large",
max_size: MAXIMUM_JSON_VALUE_SIZE_BYTES / 1024 / 1024,
),
)
end
end
end
# == Schema Information
#
# Table name: theme_settings
#
# id :bigint not null, primary key
# name :string(255) not null
# data_type :integer not null
# value :text
# theme_id :integer not null
# created_at :datetime not null
# updated_at :datetime not null
# json_value :jsonb
#