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 '/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 '/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 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}" 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 @dynamic_javascripts ||= [] @dynamic_javascripts << url_for(:action => 'page_tags_for_lookup') @stylesheets ||= [] @stylesheets << 'imagine_ccs' @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.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!(/