app/controllers/wiki_controller.rb in instiki-0.10.0 vs app/controllers/wiki_controller.rb in instiki-0.10.1
- old
+ new
@@ -1,354 +1,354 @@
-require 'application'
-require 'fileutils'
-require 'redcloth_for_tex'
-require 'parsedate'
-
-class WikiController < ApplicationController
-
- layout 'default', :except => [:rss_feed, :rss_with_content, :rss_with_headlines, :tex, :export_tex, :export_html]
-
- def index
- if @web_name
- redirect_show 'HomePage'
- elsif not @wiki.setup?
- redirect_to :controller => 'admin', :action => 'create_system'
- elsif @wiki.webs.length == 1
- redirect_show 'HomePage', @wiki.webs.values.first.address
- else
- redirect_to :action => 'web_list'
- end
- end
-
- # Outside a single web --------------------------------------------------------
-
- def authenticate
- if password_check(@params['password'])
- redirect_show('HomePage')
- else
- flash[:info] = password_error(@params['password'])
- redirect_to :action => 'login', :web => @web_name
- end
- end
-
- def login
- # to template
- end
-
- def web_list
- @webs = wiki.webs.values.sort_by { |web| web.name }
- end
-
-
- # Within a single web ---------------------------------------------------------
-
- def authors
- @authors = @web.select.authors
- end
-
- def export_html
- export_pages_as_zip('html') do |page|
- @page = page
- @link_mode = :export
- render_to_string 'wiki/print'
- end
- end
-
- def export_markup
- export_pages_as_zip(@web.markup) { |page| page.content }
- end
-
- def export_pdf
- file_name = "#{@web.address}-tex-#{@web.revised_on.strftime('%Y-%m-%d-%H-%M-%S')}"
- file_path = File.join(@wiki.storage_path, file_name)
-
- export_web_to_tex "#{file_path}.tex" unless FileTest.exists? "#{file_path}.tex"
- convert_tex_to_pdf "#{file_path}.tex"
- send_file "#{file_path}.pdf"
- end
-
- def export_tex
- file_name = "#{@web.address}-tex-#{@web.revised_on.strftime('%Y-%m-%d-%H-%M-%S')}.tex"
- file_path = File.join(@wiki.storage_path, file_name)
- export_web_to_tex(file_path) unless FileTest.exists?(file_path)
- send_file file_path
- end
-
- def feeds
- @rss_with_content_allowed = rss_with_content_allowed?
- # show the template
- end
-
- def list
- parse_category
- @pages_by_name = @pages_in_category.by_name
- @page_names_that_are_wanted = @pages_in_category.wanted_pages
- @pages_that_are_orphaned = @pages_in_category.orphaned_pages
- end
-
- def recently_revised
- parse_category
- @pages_by_revision = @pages_in_category.by_revision
- end
-
- def rss_with_content
- if rss_with_content_allowed?
- render_rss(hide_description = false, *parse_rss_params)
- else
- render_text 'RSS feed with content for this web is blocked for security reasons. ' +
- 'The web is password-protected and not published', '403 Forbidden'
- end
- end
-
- def rss_with_headlines
- render_rss(hide_description = true, *parse_rss_params)
- end
-
- def search
- @query = @params['query']
- @title_results = @web.select { |page| page.name =~ /#{@query}/i }.sort
- @results = @web.select { |page| page.content =~ /#{@query}/i }.sort
- all_pages_found = (@results + @title_results).uniq
- if all_pages_found.size == 1
- redirect_show(all_pages_found.first.name)
- end
- end
-
- # Within a single page --------------------------------------------------------
-
- def cancel_edit
- @page.unlock
- redirect_show
- end
-
- def edit
- if @page.nil?
- redirect_to :action => 'index'
- elsif @page.locked?(Time.now) and not @params['break_lock']
- redirect_to :web => @web_name, :action => 'locked', :id => @page_name
- else
- @page.lock(Time.now, @author)
- end
- end
-
- def locked
- # to template
- end
-
- def new
- # to template
- end
-
- def pdf
- page = wiki.read_page(@web_name, @page_name)
- safe_page_name = @page.name.gsub(/\W/, '')
- file_name = "#{safe_page_name}-#{@web.address}-#{@page.created_at.strftime('%Y-%m-%d-%H-%M-%S')}"
- file_path = File.join(@wiki.storage_path, file_name)
-
- export_page_to_tex("#{file_path}.tex") unless FileTest.exists?("#{file_path}.tex")
- # NB: this is _very_ slow
- convert_tex_to_pdf("#{file_path}.tex")
- send_file "#{file_path}.pdf"
- end
-
- def print
- @link_mode ||= :show
- # to template
- end
-
- def published
- if @web.published
- @page = wiki.read_page(@web_name, @page_name || 'HomePage')
- else
- redirect_show('HomePage')
- end
- end
-
- def revision
- get_page_and_revision
- end
-
- def rollback
- get_page_and_revision
- end
-
- def save
- redirect_to :action => 'index' if @page_name.nil?
- cookies['author'] = @params['author']
-
- begin
- page = @web.pages[@page_name]
- if @web.pages[@page_name]
- wiki.revise_page(
- @web_name, @page_name, @params['content'], Time.now,
- Author.new(@params['author'], remote_ip)
- )
- page.unlock
- else
- wiki.write_page(
- @web_name, @page_name, @params['content'], Time.now,
- Author.new(@params['author'], remote_ip)
- )
- end
- redirect_show(@page_name)
- rescue Instiki::ValidationError => e
- page.unlock if defined? page
- flash[:error] = e
- return_to_last_remembered
- end
- end
-
- def show
- if @page
- begin
- render_action 'page'
- # TODO this rescue should differentiate between errors due to rendering and errors in
- # the application itself (for application errors, it's better not to rescue the error at all)
- rescue => e
- logger.error e
- if in_a_web?
- redirect_to :web => @web_name, :action => 'edit',
- :action_suffix => "#{@page_name}?msg=#{e.message}"
- else
- raise e
- end
- end
- else
- if not @page_name.nil? and not @page_name.empty?
- redirect_to :web => @web_name, :action => 'new', :id => @page_name
- else
- render_text 'Page name is not specified', '404 Not Found'
- end
- end
- end
-
- def tex
- @tex_content = RedClothForTex.new(@page.content).to_tex
- end
-
-
- private
-
- def convert_tex_to_pdf(tex_path)
- # TODO remove earlier PDF files with the same prefix
- # TODO handle gracefully situation where pdflatex is not available
- begin
- wd = Dir.getwd
- Dir.chdir(File.dirname(tex_path))
- logger.info `pdflatex --interaction=nonstopmode #{File.basename(tex_path)}`
- ensure
- Dir.chdir(wd)
- end
- end
-
- def export_page_to_tex(file_path)
- tex
- File.open(file_path, 'w') { |f| f.write(render_to_string('wiki/tex')) }
- end
-
- def export_pages_as_zip(file_type, &block)
-
- file_prefix = "#{@web.address}-#{file_type}-"
- timestamp = @web.revised_on.strftime('%Y-%m-%d-%H-%M-%S')
- file_path = File.join(@wiki.storage_path, file_prefix + timestamp + '.zip')
- tmp_path = "#{file_path}.tmp"
-
- Zip::ZipOutputStream.open(tmp_path) do |zip_out|
- @web.select.by_name.each do |page|
- zip_out.put_next_entry("#{CGI.escape(page.name)}.#{file_type}")
- zip_out.puts(block.call(page))
- end
- # add an index file, if exporting to HTML
- if file_type.to_s.downcase == 'html'
- zip_out.put_next_entry 'index.html'
- zip_out.puts <<-EOL
- <html>
- <head>
- <META HTTP-EQUIV="Refresh" CONTENT="0;URL=HomePage.#{file_type}">
- </head>
- </html>
- EOL
- end
- end
- FileUtils.rm_rf(Dir[File.join(@wiki.storage_path, file_prefix + '*.zip')])
- FileUtils.mv(tmp_path, file_path)
- send_file file_path
- end
-
- def export_web_to_tex(file_path)
- @tex_content = table_of_contents(@web.pages['HomePage'].content, render_tex_web)
- File.open(file_path, 'w') { |f| f.write(render_to_string('wiki/tex_web')) }
- end
-
- def get_page_and_revision
- @revision = @page.revisions[@params['rev'].to_i]
- end
-
- def parse_category
- @categories = @web.categories
- @category = @params['category']
- if @categories.include?(@category)
- @pages_in_category = @web.select { |page| page.in_category?(@category) }
- @set_name = "category '#{@category}'"
- else
- @pages_in_category = PageSet.new(@web).by_name
- @set_name = 'the web'
- end
- end
-
- def parse_rss_params
- if @params.include? 'limit'
- limit = @params['limit'].to_i rescue nil
- limit = nil if limit == 0
- else
- limit = 15
- end
- start_date = Time.local(*ParseDate::parsedate(@params['start'])) rescue nil
- end_date = Time.local(*ParseDate::parsedate(@params['end'])) rescue nil
- [ limit, start_date, end_date ]
- end
-
- def remote_ip
- ip = @request.remote_ip
- logger.info(ip)
- ip
- end
-
- def render_rss(hide_description = false, limit = 15, start_date = nil, end_date = nil)
- if limit && !start_date && !end_date
- @pages_by_revision = @web.select.by_revision.first(limit)
- else
- @pages_by_revision = @web.select.by_revision
- @pages_by_revision.reject! { |page| page.created_at < start_date } if start_date
- @pages_by_revision.reject! { |page| page.created_at > end_date } if end_date
- end
-
- @hide_description = hide_description
- @response.headers['Content-Type'] = 'text/xml'
- @link_action = @web.password ? 'published' : 'show'
-
- render 'wiki/rss_feed'
- end
-
- def render_tex_web
- @web.select.by_name.inject({}) do |tex_web, page|
- tex_web[page.name] = RedClothForTex.new(page.content).to_tex
- tex_web
- end
- end
-
- def render_to_string(template_name)
- add_variables_to_assigns
- render template_name
- @performed_render = false
- @template.render_file(template_name)
- end
-
- def rss_with_content_allowed?
- @web.password.nil? or @web.published
- end
-
- def truncate(text, length = 30, truncate_string = '...')
- if text.length > length then text[0..(length - 3)] + truncate_string else text end
- end
-
-end
+require 'application'
+require 'fileutils'
+require 'redcloth_for_tex'
+require 'parsedate'
+
+class WikiController < ApplicationController
+
+ layout 'default', :except => [:rss_feed, :rss_with_content, :rss_with_headlines, :tex, :export_tex, :export_html]
+
+ def index
+ if @web_name
+ redirect_home
+ elsif not @wiki.setup?
+ redirect_to :controller => 'admin', :action => 'create_system'
+ elsif @wiki.webs.length == 1
+ redirect_home @wiki.webs.values.first.address
+ else
+ redirect_to :action => 'web_list'
+ end
+ end
+
+ # Outside a single web --------------------------------------------------------
+
+ def authenticate
+ if password_check(@params['password'])
+ redirect_home
+ else
+ flash[:info] = password_error(@params['password'])
+ redirect_to :action => 'login', :web => @web_name
+ end
+ end
+
+ def login
+ # to template
+ end
+
+ def web_list
+ @webs = wiki.webs.values.sort_by { |web| web.name }
+ end
+
+
+ # Within a single web ---------------------------------------------------------
+
+ def authors
+ @authors = @web.select.authors
+ end
+
+ def export_html
+ export_pages_as_zip('html') do |page|
+ @page = page
+ @link_mode = :export
+ render_to_string('wiki/print', use_layout = true)
+ end
+ end
+
+ def export_markup
+ export_pages_as_zip(@web.markup) { |page| page.content }
+ end
+
+ def export_pdf
+ file_name = "#{@web.address}-tex-#{@web.revised_on.strftime('%Y-%m-%d-%H-%M-%S')}"
+ file_path = File.join(@wiki.storage_path, file_name)
+
+ export_web_to_tex "#{file_path}.tex" unless FileTest.exists? "#{file_path}.tex"
+ convert_tex_to_pdf "#{file_path}.tex"
+ send_file "#{file_path}.pdf"
+ end
+
+ def export_tex
+ file_name = "#{@web.address}-tex-#{@web.revised_on.strftime('%Y-%m-%d-%H-%M-%S')}.tex"
+ file_path = File.join(@wiki.storage_path, file_name)
+ export_web_to_tex(file_path) unless FileTest.exists?(file_path)
+ send_file file_path
+ end
+
+ def feeds
+ @rss_with_content_allowed = rss_with_content_allowed?
+ # show the template
+ end
+
+ def list
+ parse_category
+ @pages_by_name = @pages_in_category.by_name
+ @page_names_that_are_wanted = @pages_in_category.wanted_pages
+ @pages_that_are_orphaned = @pages_in_category.orphaned_pages
+ end
+
+ def recently_revised
+ parse_category
+ @pages_by_revision = @pages_in_category.by_revision
+ end
+
+ def rss_with_content
+ if rss_with_content_allowed?
+ render_rss(hide_description = false, *parse_rss_params)
+ else
+ render_text 'RSS feed with content for this web is blocked for security reasons. ' +
+ 'The web is password-protected and not published', '403 Forbidden'
+ end
+ end
+
+ def rss_with_headlines
+ render_rss(hide_description = true, *parse_rss_params)
+ end
+
+ def search
+ @query = @params['query']
+ @title_results = @web.select { |page| page.name =~ /#{@query}/i }.sort
+ @results = @web.select { |page| page.content =~ /#{@query}/i }.sort
+ all_pages_found = (@results + @title_results).uniq
+ if all_pages_found.size == 1
+ redirect_to_page(all_pages_found.first.name)
+ end
+ end
+
+ # Within a single page --------------------------------------------------------
+
+ def cancel_edit
+ @page.unlock
+ redirect_to_page(@page_name)
+ end
+
+ def edit
+ if @page.nil?
+ redirect_to :action => 'index'
+ elsif @page.locked?(Time.now) and not @params['break_lock']
+ redirect_to :web => @web_name, :action => 'locked', :id => @page_name
+ else
+ @page.lock(Time.now, @author)
+ end
+ end
+
+ def locked
+ # to template
+ end
+
+ def new
+ # to template
+ end
+
+ def pdf
+ page = wiki.read_page(@web_name, @page_name)
+ safe_page_name = @page.name.gsub(/\W/, '')
+ file_name = "#{safe_page_name}-#{@web.address}-#{@page.created_at.strftime('%Y-%m-%d-%H-%M-%S')}"
+ file_path = File.join(@wiki.storage_path, file_name)
+
+ export_page_to_tex("#{file_path}.tex") unless FileTest.exists?("#{file_path}.tex")
+ # NB: this is _very_ slow
+ convert_tex_to_pdf("#{file_path}.tex")
+ send_file "#{file_path}.pdf"
+ end
+
+ def print
+ @link_mode ||= :show
+ # to template
+ end
+
+ def published
+ if @web.published
+ @page = wiki.read_page(@web_name, @page_name || 'HomePage')
+ else
+ redirect_home
+ end
+ end
+
+ def revision
+ get_page_and_revision
+ end
+
+ def rollback
+ get_page_and_revision
+ end
+
+ def save
+ redirect_to :action => 'index' if @page_name.nil?
+ cookies['author'] = @params['author']
+
+ begin
+ page = @web.pages[@page_name]
+ if @web.pages[@page_name]
+ wiki.revise_page(
+ @web_name, @page_name, @params['content'], Time.now,
+ Author.new(@params['author'], remote_ip)
+ )
+ page.unlock
+ else
+ wiki.write_page(
+ @web_name, @page_name, @params['content'], Time.now,
+ Author.new(@params['author'], remote_ip)
+ )
+ end
+ redirect_to_page @page_name
+ rescue Instiki::ValidationError => e
+ page.unlock if defined? page
+ flash[:error] = e
+ return_to_last_remembered
+ end
+ end
+
+ def show
+ if @page
+ begin
+ render_action 'page'
+ # TODO this rescue should differentiate between errors due to rendering and errors in
+ # the application itself (for application errors, it's better not to rescue the error at all)
+ rescue => e
+ logger.error e
+ if in_a_web?
+ redirect_to :web => @web_name, :action => 'edit',
+ :action_suffix => "#{@page_name}?msg=#{e.message}"
+ else
+ raise e
+ end
+ end
+ else
+ if not @page_name.nil? and not @page_name.empty?
+ redirect_to :web => @web_name, :action => 'new', :id => @page_name
+ else
+ render_text 'Page name is not specified', '404 Not Found'
+ end
+ end
+ end
+
+ def tex
+ @tex_content = RedClothForTex.new(@page.content).to_tex
+ end
+
+
+ private
+
+ def convert_tex_to_pdf(tex_path)
+ # TODO remove earlier PDF files with the same prefix
+ # TODO handle gracefully situation where pdflatex is not available
+ begin
+ wd = Dir.getwd
+ Dir.chdir(File.dirname(tex_path))
+ logger.info `pdflatex --interaction=nonstopmode #{File.basename(tex_path)}`
+ ensure
+ Dir.chdir(wd)
+ end
+ end
+
+ def export_page_to_tex(file_path)
+ tex
+ File.open(file_path, 'w') { |f| f.write(render_to_string('wiki/tex')) }
+ end
+
+ def export_pages_as_zip(file_type, &block)
+
+ file_prefix = "#{@web.address}-#{file_type}-"
+ timestamp = @web.revised_on.strftime('%Y-%m-%d-%H-%M-%S')
+ file_path = File.join(@wiki.storage_path, file_prefix + timestamp + '.zip')
+ tmp_path = "#{file_path}.tmp"
+
+ Zip::ZipOutputStream.open(tmp_path) do |zip_out|
+ @web.select.by_name.each do |page|
+ zip_out.put_next_entry("#{CGI.escape(page.name)}.#{file_type}")
+ zip_out.puts(block.call(page))
+ end
+ # add an index file, if exporting to HTML
+ if file_type.to_s.downcase == 'html'
+ zip_out.put_next_entry 'index.html'
+ zip_out.puts <<-EOL
+ <html>
+ <head>
+ <META HTTP-EQUIV="Refresh" CONTENT="0;URL=HomePage.#{file_type}">
+ </head>
+ </html>
+ EOL
+ end
+ end
+ FileUtils.rm_rf(Dir[File.join(@wiki.storage_path, file_prefix + '*.zip')])
+ FileUtils.mv(tmp_path, file_path)
+ send_file file_path
+ end
+
+ def export_web_to_tex(file_path)
+ @tex_content = table_of_contents(@web.pages['HomePage'].content, render_tex_web)
+ File.open(file_path, 'w') { |f| f.write(render_to_string('wiki/tex_web')) }
+ end
+
+ def get_page_and_revision
+ @revision = @page.revisions[@params['rev'].to_i]
+ end
+
+ def parse_category
+ @categories = @web.categories
+ @category = @params['category']
+ if @categories.include?(@category)
+ @pages_in_category = @web.select { |page| page.in_category?(@category) }
+ @set_name = "category '#{@category}'"
+ else
+ @pages_in_category = PageSet.new(@web).by_name
+ @set_name = 'the web'
+ end
+ end
+
+ def parse_rss_params
+ if @params.include? 'limit'
+ limit = @params['limit'].to_i rescue nil
+ limit = nil if limit == 0
+ else
+ limit = 15
+ end
+ start_date = Time.local(*ParseDate::parsedate(@params['start'])) rescue nil
+ end_date = Time.local(*ParseDate::parsedate(@params['end'])) rescue nil
+ [ limit, start_date, end_date ]
+ end
+
+ def remote_ip
+ ip = @request.remote_ip
+ logger.info(ip)
+ ip
+ end
+
+ def render_rss(hide_description = false, limit = 15, start_date = nil, end_date = nil)
+ if limit && !start_date && !end_date
+ @pages_by_revision = @web.select.by_revision.first(limit)
+ else
+ @pages_by_revision = @web.select.by_revision
+ @pages_by_revision.reject! { |page| page.created_at < start_date } if start_date
+ @pages_by_revision.reject! { |page| page.created_at > end_date } if end_date
+ end
+
+ @hide_description = hide_description
+ @response.headers['Content-Type'] = 'text/xml'
+ @link_action = @web.password ? 'published' : 'show'
+
+ render 'wiki/rss_feed'
+ end
+
+ def render_tex_web
+ @web.select.by_name.inject({}) do |tex_web, page|
+ tex_web[page.name] = RedClothForTex.new(page.content).to_tex
+ tex_web
+ end
+ end
+
+ def render_to_string(template_name, with_layout = false)
+ add_variables_to_assigns
+ @content_for_layout = @template.render_file(template_name)
+ if with_layout then @template.render_file('layouts/default');
+ else @content_for_layout; end
+ end
+
+ def rss_with_content_allowed?
+ @web.password.nil? or @web.published
+ end
+
+ def truncate(text, length = 30, truncate_string = '...')
+ if text.length > length then text[0..(length - 3)] + truncate_string else text end
+ end
+
+end