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: #

<%= display_value(@obj.title) %>

# # The named route is 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