lib/tasks/themes.rake
require Rails.root.join('commonlib', 'rblib', 'git')
namespace :themes do
# Alias the module so we don't need the MySociety prefix here
Git = MySociety::Git
def all_themes_dir
File.join(Rails.root,"lib","themes")
end
def theme_dir(theme_name)
File.join(all_themes_dir, theme_name)
end
def old_all_themes_dir(theme_name)
File.join(Rails.root, "vendor", "plugins", theme_name)
end
def possible_theme_dirs(theme_name)
[theme_dir(theme_name), old_all_themes_dir(theme_name)]
end
def installed?(theme_name)
possible_theme_dirs(theme_name).any? { |dir| File.directory? dir }
end
def usage_tag(version)
"use-with-alaveteli-#{version}"
end
def uninstall(theme_name, verbose=false)
possible_theme_dirs(theme_name).each do |dir|
run_hook(theme_name, 'uninstall', verbose) if File.directory?(dir)
end
end
def run_hook(theme_name, hook_name, verbose=false)
directory = theme_dir(theme_name)
hook_file = File.join(directory, "#{hook_name}.rb")
if File.exist? hook_file
puts "Running #{hook_name} hook in #{directory}" if verbose
load hook_file
end
end
def move_old_theme(old_theme_directory)
puts "There was an old-style theme at #{old_theme_directory}" if verbose
# remove trailing slashes
old_theme_directory.gsub!(/\/\z/, '')
moved_directory = "#{ old_theme_directory }-moved"
begin
File.rename old_theme_directory, moved_directory
rescue Errno::ENOTEMPTY, Errno::EEXIST
raise "Tried to move #{old_theme_directory} out of the way, " \
"but #{moved_directory} already existed"
end
end
def committishes_to_try
result = []
theme_branch = AlaveteliConfiguration.theme_branch
result.push "origin/#{theme_branch}" if theme_branch
result.push usage_tag(ALAVETELI_VERSION)
hotfix_match = /^(\d+\.\d+\.\d+)(\.\d+)+/.match(ALAVETELI_VERSION)
result.push usage_tag(hotfix_match[1]) if hotfix_match
minor_match = /^(\d+\.\d+)(\.\d+)+/.match(ALAVETELI_VERSION)
result.push usage_tag(minor_match[1]) if minor_match
result
end
def checkout_best_option(theme_name)
theme_directory = theme_dir theme_name
all_failed = true
committishes_to_try.each do |committish|
if Git.committish_exists? theme_directory, committish
puts "Checking out #{committish}" if verbose
Git.checkout theme_directory, committish
all_failed = false
break
elsif verbose
puts "Failed to find #{committish}; skipping..."
end
end
puts "Falling to using HEAD instead" if all_failed && verbose
end
def install_theme(theme_url, verbose, deprecated=false)
FileUtils.mkdir_p all_themes_dir
deprecation_string = deprecated ? " using deprecated THEME_URL" : ""
theme_name = theme_url_to_theme_name theme_url
puts "Installing theme #{theme_name}#{deprecation_string} from #{theme_url}"
# Make sure any uninstall hooks have been run:
uninstall(theme_name, verbose) if installed?(theme_name)
theme_directory = theme_dir theme_name
# Is there an old-style theme directory there? If so, move it
# out of the way so that there's no risk that work is lost:
if File.directory? theme_directory
unless Git.non_bare_repository? theme_directory
move_old_theme theme_directory
end
end
# If there isn't a directory there already, clone it into place:
unless File.directory? theme_directory
unless system "git", "clone", theme_url, theme_directory
raise "Cloning from #{theme_url} to #{theme_directory} failed"
end
end
# Set the URL for origin in case it has changed, and fetch from there:
Git.remote_set_url theme_directory, 'origin', theme_url
Git.fetch theme_directory, 'origin'
# Check that checking-out a new commit will be safe:
unless Git.status_clean theme_directory
raise "There were uncommitted changes in #{theme_directory}"
end
unless Git.is_HEAD_pushed? theme_directory
raise "The current work in #{theme_directory} is unpushed"
end
# Now try to checkout various commits in order of preference:
checkout_best_option theme_name
# Finally run the install hooks:
run_hook(theme_name, 'install', verbose)
run_hook(theme_name, 'post_install', verbose)
puts "#{theme_name} successfully installed in: #{theme_directory}"
puts ""
end
def theme_urls
urls = AlaveteliConfiguration.theme_urls || []
urls.delete_if(&:blank?)
end
desc "Install themes specified in the config file's THEME_URLS"
task install: :environment do
verbose = true
theme_urls.each do |theme_url|
install_theme(theme_url, verbose)
end
# Old version of the above, for backwards compatibility
unless AlaveteliConfiguration.theme_url.blank?
install_theme(AlaveteliConfiguration.theme_url, verbose, deprecated=true)
end
end
def locale_extensions(locale)
locale_extensions = if AlaveteliLocalization.default_locale?(locale)
['']
else
[".#{locale}"]
end
if !AlaveteliLocalization.default_locale?(locale) &&
locale.to_s.include?('_')
locale_extensions << ".#{locale.to_s.split('_').first}"
end
locale_extensions
end
def template_file(template_name, theme_name, locale)
locale_extensions(locale).each do |locale_extension|
filename = "#{template_name}#{locale_extension}.html.erb"
filepath = "lib/themes/#{theme_name}/lib/views/help/#{filename}"
return filepath if File.exist?(filepath)
end
nil
end
def missing_help_info?(help_template_info, locale, theme_name)
template_file = template_file(help_template_info[:name], theme_name, locale)
missing_templates = []
missing_sections = []
if !template_file
missing_templates << template_file
puts "Missing help template: #{help_template_info[:name]} #{locale}"
else
contents = File.read(template_file)
help_template_info[:sections].each do |section|
unless contents.include?("##{section}")
missing_sections << section
puts "Missing section: #{section} in template #{help_template_info[:name]}"
end
end
end
if missing_templates.empty? && missing_sections.empty?
false
else
true
end
end
desc "Check that all help sections referred to in the application are present in theme"
task check_help_sections: :environment do
intro_message = <<-EOF
Checking that all help templates linked to from Alaveteli are present in the theme,
and that all sections linked to from Alaveteli are present in the templates. For
missing templates, see the examples in the alavetelitheme theme. For
missing sections, create a section in the relevant template. For example, if the
section 'example' is listed as missing, create a section with the following HTML
structure:
<dt id="example">Section title <a href="#example">#</a> </dt>
<dd>Contents of the section
</dd>
EOF
puts intro_message
theme_names = theme_urls.map do |theme_url|
theme_url_to_theme_name(theme_url)
end
help_templates_info = [{ name: 'about',
sections: %w[whybother_them
reporting
reporting_unavailable] },
{ name: 'alaveteli',
sections: [] },
{ name: 'api',
sections: [] },
{ name: 'contact',
sections: [] },
{ name: 'credits',
sections: ['helpus'] },
{ name: 'officers',
sections: ['copyright'] },
{ name: 'privacy',
sections: %w[email_address
full_address
postal_answer
public_request
real_name] },
{ name: 'requesting',
sections: %w[focused
data_protection
missing_body
quickly_response] },
{ name: 'unhappy',
sections: %w[internal_review
other_means] },
{ name: '_why_they_should_reply_by_email',
sections: [] }]
theme_names.each do |theme_name|
AlaveteliLocalization.available_locales.each do |locale|
puts ""
puts "theme: #{theme_name} locale: #{locale}"
puts ""
missing = false
help_templates_info.each do |help_template_info|
if missing_help_info?(help_template_info, locale, theme_name)
missing = true
end
end
puts "No missing templates or sections" unless missing
end
end
end
end