class Management::CmsController < Management::ApplicationController # :nodoc:
before_filter :check_permissions
before_filter :block_basic_users, :except => [
:index, :edit_page_content,
:include_codepress, :disable_caching, :garbage_collect,
:select_page, :list_pages_select, :request_review,
:toolbar_preview, :toolbar_edit,
:create_file_link, :upload_file, :receive_file,
:upload_image, :receive_image, :crop_image, :save_crop, :upload_status,
:upload_thumb, :crop_thumb, :save_crop_thumb,
:upload_feature_image, :crop_feature_image, :save_crop_feature_image,
:receive_gallery, :complete_gallery, :gallery_setup, :add_to_gallery,
:gallery_management, :select_gallery, :set_gallery_order, :save_gallery_settings,
:sort_images, :sort_images_save,
:image_details, :update_caption,
:delete_photo, :delete_gallery,
:pages, :list_pages, :edit_page, :page_attribute, :set_page_version
]
before_filter :convert_invalid_chars_in_params
upload_status_for :receive_image
upload_status_for :add_to_gallery
cache_sweeper :cms_content_sweeper
def check_permissions
if !user_has_permission?(:manage_cms)
render '/imagine_cms/errors/permission_denied'
return false
end
end
def block_basic_users
return true unless UseCmsAccessLevels
unless user_has_permission?(:manage_cms_full_access) && @user.cms_allowed_sections.to_s.strip.blank?
render '/imagine_cms/errors/permission_denied'
return false
end
end
def validate_user_access
unless @user.cms_allowed_sections.to_s.strip.blank?
allowed_sections = @user.cms_allowed_sections.split(',').map { |s| s.strip }.reject { |s| s.blank? }
if @pg
path = '/' + @pg.path
else
parent = CmsPage.find_by_id(params[:parent_id] || params[:pg][:parent_id]) rescue nil
return false if !parent
path = '/' + parent.path
end
allowed = false
allowed_sections.each { |s| allowed ||= (path =~ /^#{s}/) }
if !allowed
respond_to do |wants|
wants.js { render :text => "Sorry, you don't have permission to edit this page." }
wants.html { redirect_to "/#{@pg.path}#{@pg.path == '' ? '' : '/'}version/#{@pg.version}" }
end
return false
end
end
return true
end
def index
end
def templates
@temps = CmsTemplate.find(:all, :order => 'name')
end
def edit_template
@temp = CmsTemplate.find_by_id(params[:id]) || CmsTemplate.new
if request.post?
@temp.assign_attributes(params[:temp])
begin
@pg = CmsPage.new
@page_objects = HashObject.new
render_to_string :inline => @temp.content
rescue Exception => e
message = e.message
flash.now[:error] = "
#{ERB::Util.html_escape(message)}
".html_safe
logger.debug e
return
end
# this must come after the render_to_string so that we capture template
# options embedded in snippets
@temp.options = @template_options
if !@temp.save
flash.now[:error] = @temp.errors.full_messages.join('
')
else
flash[:notice] = 'Template saved.'
redirect_to :action => 'edit_template', :id => @temp.id and return
end
end
end
def snippets
@snippets = CmsSnippet.find(:all, :order => 'name')
end
def edit_snippet
@snip = CmsSnippet.find_by_id(params[:id]) || CmsSnippet.new
if request.post?
@snip.assign_attributes(params[:snip])
begin
@pg = CmsPage.new
@page_objects = HashObject.new
render_to_string :inline => @snip.content
rescue Exception => e
message = e.message
flash.now[:error] = "#{ERB::Util.html_escape(message)}
".html_safe
logger.debug e
return
end
if !@snip.save
@error = @snip.errors.full_messages.join('
')
else
flash[:notice] = 'Snippet saved.'
redirect_to :action => 'edit_snippet', :id => @snip.id and return
end
end
end
#
# AKN 2012-11-08: This was never really a good idea. Need to figure out a better way. Disabling for now.
#
# def edit_master
# @file_type = case params[:id]
# when 'template' then 'html'
# when 'web_stylesheet', 'print_stylesheet' then 'css'
# else nil
# end
#
# filename = case params[:id]
# when 'template' then File.join('app', 'views', 'layouts', 'application.rhtml')
# when 'web_stylesheet' then File.join('public', 'stylesheets', 'default.css')
# when 'print_stylesheet' then File.join('public', 'stylesheets', 'print.css')
# when 'ie_stylesheet' then File.join('public', 'stylesheets', 'ie.css')
# when 'ie6_stylesheet' then File.join('public', 'stylesheets', 'ie6.css')
# end
# filename = File.join(Rails.root, filename)
#
# case request.method
# when :get
# @file_content = File.open(filename, 'r').read
# when :post
# begin
# @pg = CmsPage.new
# @page_objects = HashObject.new
# render_to_string :inline => params[:file_content]
# rescue Exception => e
# message = e.message
# flash.now[:error] = "#{ERB::Util.html_escape(message)}
"
# logger.debug e
# return
# end
#
# begin
# if params[:file_content].empty?
# flash[:error] = 'An error occurred, please contact support.'
# else
# File.open(filename, 'w') { |f| f.write(params[:file_content]) }
# flash[:notice] = 'File saved.'
# end
#
# CmsPage.find(:all).each do |page|
# expire_page :controller => 'cms/content', :action => 'show', :content_path => page.path.split('/')
# end
#
# redirect_to :action => 'edit_master', :id => params[:id]
# rescue Exception => e
# message = e.message
# flash.now[:error] = "#{ERB::Util.html_escape(message)}
"
# log_error(e)
# end
# end
# end
def pages
@page_levels = [ '' ].concat((params[:path] || session[:cms_pages_path] || '').split('/').reject { |l| l.empty? })
@page_levels << ''
@path = ''
@page = nil
end
def list_pages
@page_level = params[:level].to_i
@parent = CmsPage.find_by_id(params[:parent_id])
if @page_level == 0
render :partial => 'list_page', :locals => { :list_page => CmsPage.find(1) } and return
else
if @parent
@pages = @parent.children
session[:cms_pages_path] = @parent.path
else
@pages = nil
end
end
render :partial => 'list_pages'
end
def edit_page
@pg = CmsPage.find_by_id(params[:id])
validate_user_access or return
@pg ||= CmsPage.new
@parent = @pg.parent || CmsPage.find_by_id(params[:parent_id])
if @parent
@pg.parent ||= @parent
@pg.template ||= @parent.template
end
@attrs = CmsPageObject.find(:all, :conditions => [ "obj_type = 'attribute'" ], :order => 'name').map { |attr| attr.name }.uniq
if params[:mode] == 'ajax_new' || params[:mode] == 'ajax_edit'
@pg.published_version = -1 if params[:mode] == 'ajax_new'
load_page_objects
load_template_options
render :partial => 'edit_page' and return
end
if request.post?
params[:pg] ||= {}
if params[:pg][:article_date_year]
params[:pg][:article_date] = Time.utc(params[:pg].delete(:article_date_year),
params[:pg].delete(:article_date_month),
params[:pg].delete(:article_date_day))
end
if params[:pg][:article_end_date_year]
params[:pg][:article_end_date] = Time.utc(params[:pg].delete(:article_end_date_year),
params[:pg].delete(:article_end_date_month),
params[:pg].delete(:article_end_date_day))
end
if params[:pg][:published_date_year]
params[:pg][:published_date] = Time.utc(params[:pg].delete(:published_date_year),
params[:pg].delete(:published_date_month),
params[:pg].delete(:published_date_day))
end
if params[:pg][:expires]
date = Time.utc(params[:pg].delete(:expiration_date_year),
params[:pg].delete(:expiration_date_month),
params[:pg].delete(:expiration_date_day))
params[:pg][:expiration_date] = date if params[:pg][:expires] == 'true'
end
@pg.assign_attributes(params[:pg])
unless params[:use_article_date_range].to_i > 0
@pg.article_end_date = nil
end
@pg.updated_by ||= session[:user_id]
@pg.updated_by_username ||= session[:user_username]
save_function = @pg.new_record? ? 'save' : 'save_without_revision'
if @pg.send(save_function)
# now try to save tags
begin
tags_to_delete = @pg.tags
params[:tags].split(',').map { |t| t.strip }.reject { |t| t.empty? }.compact.each do |t|
@pg.tags.create(:name => t) unless @pg.tags.find_by_name(t)
tags_to_delete.reject! { |tag| tag.name == t }
end
tags_to_delete.each { |t| t.destroy }
rescue Exception => e
logger.debug e
end
# now try to save page objects (just attributes in this case)
begin
objects_to_delete = @pg.objects.find(:all, :conditions => [ "obj_type = 'attribute' or obj_type = 'option'" ])
(params[:page_objects] || {}).each do |key,val|
next if key.empty? || val.empty?
key =~ /^obj-(\w+?)-(.+?)$/
obj = @pg.objects.find(:first, :conditions => [ "name = ? and obj_type = ?", $2, $1 ])
obj ||= @pg.objects.build(:name => $2, :obj_type => $1)
obj.content = val
obj.save
objects_to_delete.reject! { |obj| obj.name == $2 }
end
objects_to_delete.each { |t| t.destroy }
rescue Exception => e
logger.debug e
end
render :update do |page|
case params[:return_to]
when 'preview'
page.redirect_to "/#{@pg.path}/version/#{@pg.published_version > 0 ? @pg.published_version : @pg.version}"
else
flash[:notice] = 'Page saved.'
session[:cms_pages_path] = @pg.path
page.redirect_to :action => 'pages'
end
end
else
# save failed, display errors
render :update do |page|
page.replace_html 'save_errors', @pg.errors.full_messages.join('
')
page << "try { $('btn_next').disabled = false; } catch (e) {}"
page << "try { $('btn_finish').disabled = false; } catch (e) {}"
page << "try { $('btn_save').disabled = false; $('btn_save').value = 'Save'; } catch (e) {}"
end and return
end
end
end
def delete_page
@pg = CmsPage.find_by_id(params[:id])
if !@pg
flash[:error] = "Sorry, couldn't find the requested page."
elsif @pg.children.size > 0
flash[:error] = "This page contains other pages. Please delete those first if you are sure you want to delete this page."
elsif @pg.id == 1
flash[:error] = "You cannot delete the home page."
else
flash[:notice] = "Page deleted."
session[:cms_pages_path] = @pg.parent.path rescue nil
@pg.destroy
end
redirect_to :action => 'pages'
end
def select_page
@page_levels = [ '' ].concat((params[:path] || session[:cms_pages_path] || '').split('/').reject { |l| l.empty? })
@page_levels << ''
@path = ''
@page = nil
render :layout => false
end
def list_pages_select
@page_level = params[:level].to_i
@parent = CmsPage.find_by_id(params[:parent_id])
if @page_level == 0
render :partial => 'list_page_select', :locals => { :list_page_select => CmsPage.find(1) } and return
else
if @parent
@pages = @parent.children
session[:cms_pages_path] = @parent.path
else
@pages = nil
end
end
render :partial => 'list_pages_select'
end
def show_template_options
@pg = CmsPage.find_by_id(params[:id]) || CmsPage.new
@pg.cms_template_id = params[:template_id]
load_page_objects
load_template_options
render :partial => 'template_options'
end
def page_attribute
render :nothing => true and return unless params[:name]
@page_objects = HashObject.new({ params[:name] => params[:value] })
render :partial => 'page_attribute', :locals => { :name => params[:name] }
end
def edit_page_content
@pg = CmsPage.find(params[:id])
validate_user_access or return
@page_objects = HashObject.new(params[:page_objects] || {})
if request.get?
@pg.revert_to(params[:version]) if params[:version]
@pg.objects.find(:all, :conditions => [ 'cms_page_version = ?', @pg.version ]).each do |obj|
key = "obj-#{obj.obj_type.to_s}-#{obj.name}"
@page_objects[key] = obj.content.html_safe
end
# set "legacy" vars
@content_levels = @pg.path.split('/')
params[:section] = @content_levels.size < 1 ? '' : @content_levels.first
params[:subsection] = @content_levels[1] unless @content_levels.size < 3
if @content_levels.size == 1
params[:page] = 'index'
elsif @content_levels.size > 1
params[:page] = @content_levels.last
end
@page_title = @pg.title
@cms_head ||= ''
@cms_head << ""
@template_content = substitute_placeholders(@pg.template.content, @pg)
render :layout => 'application'
elsif request.post?
CmsPage.transaction do
# need to revise this later if we implement deletion of page objects
old_objs = @pg.objects.find(:all, :conditions => [ 'cms_page_version = ?', @pg.version ])
@pg.updated_by = session[:user_id]
@pg.updated_by_username = session[:user_username]
# if basic user, make sure published version is not set to 'latest'
if (UseCmsAccessLevels && !user_has_permission?(:manage_cms_full_access)) && @pg.published_version == 0
@pg.published_version = @pg.version
end
@pg.updated_on = Time.now.utc
@pg.save
# do a little bit of classification... for now, just identify page lists
page_lists = []
@page_objects.each do |key,val|
key =~ /^obj-(\w+?)-(\w+?)-sources-tag-count$/
if $1 == 'page_list'
page_lists << "obj-#{$1}-#{$2}"
end
end
# run through page lists and do a little housekeeping
page_lists.each do |key|
# optimize source lists: tags
if @page_objects["#{key}-sources-tag-count"].to_i > 0
tags = []
for i in 0...@page_objects["#{key}-sources-tag-count"].to_i
tags << @page_objects["#{key}-sources-tag#{i}"]
end
tags.reject! { |tag| tag.empty? }
@page_objects["#{key}-sources-tag-count"] = tags.size
tags.each_with_index do |tag, i|
@page_objects["#{key}-sources-tag#{i}"] = tag
end
end
# optimize source lists: folders
if @page_objects["#{key}-sources-folder-count"].to_i > 0
folders = []
for i in 0...@page_objects["#{key}-sources-folder-count"].to_i
folders << @page_objects["#{key}-sources-folder#{i}"]
end
folders.reject! { |folder| folder.empty? }
@page_objects["#{key}-sources-folder-count"] = folders.size
folders.each_with_index do |folder, i|
@page_objects["#{key}-sources-folder#{i}"] = folder
end
end
# consolidate date picker fields
if @page_objects["#{key}-date-range-custom-start_year"]
@page_objects["#{key}-date-range-custom-start"] =
Time.utc(@page_objects.delete("#{key}-date-range-custom-start_year"),
@page_objects.delete("#{key}-date-range-custom-start_month"),
@page_objects.delete("#{key}-date-range-custom-start_day"))
end
if @page_objects["#{key}-date-range-custom-end_year"]
@page_objects["#{key}-date-range-custom-end"] =
Time.utc(@page_objects.delete("#{key}-date-range-custom-end_year"),
@page_objects.delete("#{key}-date-range-custom-end_month"),
@page_objects.delete("#{key}-date-range-custom-end_day"))
end
end
@page_objects.each do |key,val|
key =~ /^obj-(\w+?)-(.+?)$/
obj = @pg.objects.build(:name => $2, :obj_type => $1)
# do a little bit of "censorship" to fix up Word pastes
if val.is_a?(String)
# all meta and link tags
val.gsub!(/(<\/?)(meta|link)(.*?)>/m, '')
# the dreaded MsoNormal
val.gsub!(' class="MsoNormal"', '')
# remove all font-family/font-size css styles, as well as font tags
val.gsub!(/font-(?:family|size):.*?(;|")/, '\3')
val.gsub!(/(.*?)<\/font>/, '\1')
# strange conditional IE stuff
val.gsub!(//m, '')
# not even sure what these are supposed to be
val.gsub!(/(.*?)<\/xml>/m, '')
# pirate styles not welcome
val.gsub!(/