module RailsConnector
#
# This controller provides an interface for generating PDFs from CMS objects.
# It has two modes: internal mode and external mode.
#
# =Internal mode
#
# In the internal mode the PDF generator comes with a ready-made action, index
.
# You can customize this action and/or add your own custom actions.
#
# To add your own action you need to provide:
# - a controller action
# - an XML template
# - an XSL stylesheet
#
# The XML template must be named ACTION_NAME.html.erb
and the XSL stylesheet
# must be named ACTION_NAME.xsl
. Place these files into RAILS_ROOT/app/views/pdf/
.
#
# Use the module RailsConnector::FopOnRails
to generate the PDF.
# Inside your action, the XML template has already been rendered and can be referenced by means of @xml_path
.
# The XSL stylesheet can be referenced by means of @xsl_path
.
#
# In your ERb template you can use @obj
to reference the CMS object and the display_value
method to
# render its attributes:
#
pdf_with_action
:
# <%= link_to('Generate custom PDF', pdf_with_action_path(:action => 'my_action', :id => 1234)) %>
# # This will produce Generate custom PDF
#
# =External mode
#
# In the external mode the PDF generator has a named route pdf_external
# and is accessed through the URL /pdf/external
.
#
# In order to produce a PDF file, the GET parameters xml_url
and xsl_url
# need to be provided.
#
# Optional GET-parameters are:
# filename: string
# tidy: true or false (default is false)
#
# Example:
# curl -d "xml_url=http://example.com/test.xml&xsl_url=http://example.com/test.xsl" -g http://localhost:3000/pdf/external
#
# To allow a host to be the source for XML or XSL, add it to the so called "white list". Add
# following to RAILS_ROOT/config/initializers/rails_connector.rb
to do that:
# RailsConnector::Configuration::PdfGenerator.host_whitelist(
# 'example1.com',
# 'example2.com',
# 'example3.com'
# )
#
# You can add as many hosts as you need. If no hosts have been added to the "white list", then the
# PDF generator will refuse to produce PDF files from any external source.
#
# If the host given through xml_url
or xsl_url
is not included in the
# "white list", then an error message will be rendered as inline text with response status "403
# Forbidden".
#
class DefaultPdfController < DefaultCmsController
# Returns false by default to exclude this controller from regular Obj dispatch.
# @see DefaultCmsController#use_for_obj_dispatch?
def self.use_for_obj_dispatch?
# If this method would to return true, an Obj with ObjClass "pdf" would be delivered by
# the PdfController as an actual generated Pdf, which would be surprising to most developers.
false
end
before_filter :dump_obj
before_filter :compute_xsl_path
before_filter :send_pdf
after_filter :cleanup_xml
#
# Generates a PDF from a CMS object.
#
# Takes a GET-parameter, id
, to determine the object.
#
# As a default, the built-in XML template and XSL stylesheet will be used. You can replace them
# with the files RAILS_ROOT/app/views/pdf/index.html.erb
and RAILS_ROOT/app/views/pdf/index.xsl
respectively.
#
# By default, the PDF will contain the title and the body of the object.
# The PDF will be named NAME_OF_THE_OBJECT.pdf
.
#
# The named route is called pdf
and is accessed through
# /pdf/OBJECT_ID
.
#
# Example:
#
# <%= link_to 'Generate PDF', pdf_path(@obj) %>
# # This will generate a PDF containing the title and the body of the current object
#
def index
end
protected
def send_pdf
send_file(
FopOnRails.generate_pdf(@xml_path, @xsl_path),
:filename => "#{@obj.name}.pdf",
:type => 'application/pdf'
)
end
private
def dump_obj
base_folder = Rails.root + "tmp"
FileUtils.mkdir_p(base_folder)
@xml_path = File.join(base_folder, "#{Time.now.to_f}_#{$$}")
data = render_to_string(:controller => 'pdf', :action => action_name, :layout => false)
File.open(@xml_path, 'w') do |f|
f.write(data)
end
end
def compute_xsl_path
@xsl_path = nil
view_paths.each do |view_path|
xsl_path = "#{view_path}/#{controller_name}/#{action_name}.xsl"
if File.exist?(xsl_path)
@xsl_path = xsl_path
return
end
end
raise 'No XSL template found' unless @xsl_path
end
def cleanup_xml
FileUtils.rm_rf(@xml_path)
end
end
end