mirror of
https://github.com/discourse/discourse.git
synced 2025-05-31 05:08:09 +08:00
FEATURE: Import and export themes in a .tar.gz format (#6916)
This commit is contained in:
@ -4,6 +4,8 @@ require_dependency 'upload_creator'
|
||||
|
||||
class RemoteTheme < ActiveRecord::Base
|
||||
|
||||
class ImportError < StandardError; end
|
||||
|
||||
ALLOWED_FIELDS = %w{scss embedded_scss head_tag header after_header body_tag footer}
|
||||
|
||||
GITHUB_REGEXP = /^https?:\/\/github\.com\//
|
||||
@ -14,15 +16,22 @@ class RemoteTheme < ActiveRecord::Base
|
||||
joins("JOIN themes ON themes.remote_theme_id = remote_themes.id").where.not(remote_url: "")
|
||||
}
|
||||
|
||||
def self.update_tgz_theme(filename, user: Discourse.system_user)
|
||||
def self.extract_theme_info(importer)
|
||||
JSON.parse(importer["about.json"])
|
||||
rescue TypeError, JSON::ParserError
|
||||
raise ImportError.new I18n.t("themes.import_error.about_json")
|
||||
end
|
||||
|
||||
def self.update_tgz_theme(filename, match_theme: false, user: Discourse.system_user)
|
||||
importer = ThemeStore::TgzImporter.new(filename)
|
||||
importer.import!
|
||||
|
||||
theme_info = JSON.parse(importer["about.json"])
|
||||
|
||||
theme = Theme.find_by(name: theme_info["name"])
|
||||
theme_info = RemoteTheme.extract_theme_info(importer)
|
||||
theme = Theme.find_by(name: theme_info["name"]) if match_theme
|
||||
theme ||= Theme.new(user_id: user&.id || -1, name: theme_info["name"])
|
||||
|
||||
theme.component = theme_info["component"].to_s == "true"
|
||||
|
||||
remote_theme = new
|
||||
remote_theme.theme = theme
|
||||
remote_theme.remote_url = ""
|
||||
@ -42,7 +51,7 @@ class RemoteTheme < ActiveRecord::Base
|
||||
importer = ThemeStore::GitImporter.new(url.strip, private_key: private_key, branch: branch)
|
||||
importer.import!
|
||||
|
||||
theme_info = JSON.parse(importer["about.json"])
|
||||
theme_info = RemoteTheme.extract_theme_info(importer)
|
||||
component = [true, "true"].include?(theme_info["component"])
|
||||
theme = Theme.new(user_id: user&.id || -1, name: theme_info["name"], component: component)
|
||||
|
||||
@ -74,10 +83,11 @@ class RemoteTheme < ActiveRecord::Base
|
||||
end
|
||||
|
||||
def update_remote_version
|
||||
return unless is_git?
|
||||
importer = ThemeStore::GitImporter.new(remote_url, private_key: private_key, branch: branch)
|
||||
begin
|
||||
importer.import!
|
||||
rescue ThemeStore::GitImporter::ImportFailed => err
|
||||
rescue RemoteTheme::ImportError => err
|
||||
self.last_error_text = err.message
|
||||
else
|
||||
self.updated_at = Time.zone.now
|
||||
@ -87,7 +97,6 @@ class RemoteTheme < ActiveRecord::Base
|
||||
end
|
||||
|
||||
def update_from_remote(importer = nil, skip_update: false)
|
||||
return unless remote_url
|
||||
cleanup = false
|
||||
|
||||
unless importer
|
||||
@ -95,7 +104,7 @@ class RemoteTheme < ActiveRecord::Base
|
||||
importer = ThemeStore::GitImporter.new(remote_url, private_key: private_key, branch: branch)
|
||||
begin
|
||||
importer.import!
|
||||
rescue ThemeStore::GitImporter::ImportFailed => err
|
||||
rescue RemoteTheme::ImportError => err
|
||||
self.last_error_text = err.message
|
||||
return self
|
||||
else
|
||||
@ -103,7 +112,7 @@ class RemoteTheme < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
|
||||
theme_info = JSON.parse(importer["about.json"])
|
||||
theme_info = RemoteTheme.extract_theme_info(importer)
|
||||
|
||||
theme_info["assets"]&.each do |name, relative_path|
|
||||
if path = importer.real_path(relative_path)
|
||||
@ -114,34 +123,15 @@ class RemoteTheme < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
|
||||
Theme.targets.keys.each do |target|
|
||||
next if target == :settings || target == :translations
|
||||
ALLOWED_FIELDS.each do |field|
|
||||
lookup =
|
||||
if field == "scss"
|
||||
"#{target}.scss"
|
||||
elsif field == "embedded_scss" && target == :common
|
||||
"embedded.scss"
|
||||
else
|
||||
"#{field}.html"
|
||||
end
|
||||
|
||||
value = importer["#{target}/#{lookup}"]
|
||||
theme.set_field(target: target.to_sym, name: field, value: value)
|
||||
end
|
||||
end
|
||||
|
||||
settings_yaml = importer["settings.yaml"] || importer["settings.yml"]
|
||||
theme.set_field(target: :settings, name: "yaml", value: settings_yaml)
|
||||
|
||||
I18n.available_locales.each do |locale|
|
||||
value = importer["locales/#{locale}.yml"]
|
||||
theme.set_field(target: :translations, name: locale, value: value)
|
||||
end
|
||||
|
||||
self.license_url = theme_info["license_url"]
|
||||
self.about_url = theme_info["about_url"]
|
||||
|
||||
importer.all_files.each do |filename|
|
||||
next unless opts = ThemeField.opts_from_file_path(filename)
|
||||
value = importer[filename]
|
||||
theme.set_field(opts.merge(value: value))
|
||||
end
|
||||
|
||||
if !skip_update
|
||||
self.remote_updated_at = Time.zone.now
|
||||
self.remote_version = importer.version
|
||||
@ -214,6 +204,10 @@ class RemoteTheme < ActiveRecord::Base
|
||||
"https://github.com/#{org_repo}"
|
||||
end
|
||||
end
|
||||
|
||||
def is_git?
|
||||
remote_url.present?
|
||||
end
|
||||
end
|
||||
|
||||
# == Schema Information
|
||||
|
Reference in New Issue
Block a user