diff --git a/app/controllers/admin/themes_controller.rb b/app/controllers/admin/themes_controller.rb index d6bc528c3fd..00e17991b83 100644 --- a/app/controllers/admin/themes_controller.rb +++ b/app/controllers/admin/themes_controller.rb @@ -97,9 +97,10 @@ class Admin::ThemesController < Admin::AdminController # params[:bundle] used by theme CLI. params[:theme] used by admin UI bundle = params[:bundle] || params[:theme] theme_id = params[:theme_id] + update_components = params[:components] match_theme_by_name = !!params[:bundle] && !params.key?(:theme_id) # Old theme CLI behavior, match by name. Remove Jan 2020 begin - @theme = RemoteTheme.update_zipped_theme(bundle.path, bundle.original_filename, match_theme: match_theme_by_name, user: theme_user, theme_id: theme_id) + @theme = RemoteTheme.update_zipped_theme(bundle.path, bundle.original_filename, match_theme: match_theme_by_name, user: theme_user, theme_id: theme_id, update_components: update_components) log_theme_change(nil, @theme) render json: @theme, status: :created rescue RemoteTheme::ImportError => e diff --git a/app/models/remote_theme.rb b/app/models/remote_theme.rb index e95fe25c517..292ba79d7eb 100644 --- a/app/models/remote_theme.rb +++ b/app/models/remote_theme.rb @@ -30,17 +30,22 @@ class RemoteTheme < ActiveRecord::Base raise ImportError.new I18n.t("themes.import_error.about_json") end - def self.update_zipped_theme(filename, original_filename, match_theme: false, user: Discourse.system_user, theme_id: nil) + def self.update_zipped_theme(filename, original_filename, match_theme: false, user: Discourse.system_user, theme_id: nil, update_components: nil) importer = ThemeStore::ZipImporter.new(filename, original_filename) importer.import! theme_info = RemoteTheme.extract_theme_info(importer) theme = Theme.find_by(name: theme_info["name"]) if match_theme # Old theme CLI method, remove Jan 2020 theme = Theme.find_by(id: theme_id) if theme_id # New theme CLI method - theme ||= Theme.new(user_id: user&.id || -1, name: theme_info["name"]) + + existing = true + if theme.blank? + theme = Theme.new(user_id: user&.id || -1, name: theme_info["name"]) + existing = false + end theme.component = theme_info["component"].to_s == "true" - theme.child_components = theme_info["components"].presence || [] + theme.child_components = child_components = theme_info["components"].presence || [] remote_theme = new remote_theme.theme = theme @@ -48,6 +53,19 @@ class RemoteTheme < ActiveRecord::Base remote_theme.update_from_remote(importer, skip_update: true) theme.save! + + if existing && update_components.present? && update_components != "none" + child_components = child_components.map { |url| ThemeStore::GitImporter.new(url.strip).url } + + if update_components == "sync" + ChildTheme.joins(child_theme: :remote_theme).where("remote_themes.remote_url NOT IN (?)", child_components).delete_all + end + + child_components -= theme.child_themes.joins(:remote_theme).where("remote_themes.remote_url IN (?)", child_components).pluck("remote_themes.remote_url") + theme.child_components = child_components + theme.update_child_components + end + theme ensure begin diff --git a/app/models/theme.rb b/app/models/theme.rb index c20e04d9053..69f6c2899ea 100644 --- a/app/models/theme.rb +++ b/app/models/theme.rb @@ -25,6 +25,8 @@ class Theme < ActiveRecord::Base validate :component_validations + after_create :update_child_components + scope :user_selectable, ->() { where('user_selectable OR id = ?', SiteSetting.default_theme_id) } @@ -70,7 +72,7 @@ class Theme < ActiveRecord::Base notify_theme_change(with_scheme: notify_with_scheme) end - after_create do + def update_child_components if !component? && child_components.present? child_components.each do |url| url = ThemeStore::GitImporter.new(url.strip).url