1 package SL::Helper::CreatePDF;
 
   7 use English qw(-no_match_vars);
 
  10 use List::MoreUtils qw(uniq);
 
  11 use List::Util qw(first);
 
  12 use String::ShellQuote ();
 
  20 use SL::Template::LaTeX;
 
  22 use Exporter 'import';
 
  23 our @EXPORT_OK = qw(create_pdf merge_pdfs find_template);
 
  29   my ($class, %params) = @_;
 
  31   return $class->create_parsed_file(
 
  33     template_type => 'LaTeX',
 
  38 sub create_parsed_file {
 
  39   my ($class, %params) = @_;
 
  41   my $userspath       = $::lx_office_conf{paths}->{userspath};
 
  42   my $vars            = $params{variables} || {};
 
  43   my $form            = Form->new('');
 
  44   $form->{$_}         = $vars->{$_} for keys %{ $vars };
 
  45   $form->{format}     = lc($params{format} || 'pdf');
 
  46   $form->{cwd}        = getcwd();
 
  47   $form->{templates}  = $::instance_conf->get_templates;
 
  48   $form->{IN}         = $params{template};
 
  49   $form->{tmpdir}     = $form->{cwd} . '/' . $userspath;
 
  50   my ($suffix)        = $params{template} =~ m{\.(.+)};
 
  52   my ($temp_fh, $tmpfile) = File::Temp::tempfile(
 
  53     'kivitendo-printXXXXXX',
 
  54     SUFFIX => ".${suffix}",
 
  56     UNLINK => ($::lx_office_conf{debug} && $::lx_office_conf{debug}->{keep_temp_files})? 0 : 1,
 
  59   $form->{tmpfile} = $tmpfile;
 
  61   my $parser  = SL::Template::create(
 
  62     type      => ($params{template_type} || 'LaTeX'),
 
  63     source    => $form->{IN},
 
  65     myconfig  => \%::myconfig,
 
  66     userspath => $userspath,
 
  69   my $result = $parser->parse($temp_fh);
 
  76     die $parser->get_error;
 
  79   if (($params{return} || 'content') eq 'file_name') {
 
  80     my $new_name = $userspath . '/keep-' . $tmpfile;
 
  81     rename $tmpfile, $new_name;
 
  88   my $content = File::Slurp::read_file($tmpfile);
 
  96   my ($class, %params) = @_;
 
  98   return scalar(File::Slurp::read_file($params{file_names}->[0])) if scalar(@{ $params{file_names} }) < 2;
 
 100   my ($temp_fh, $temp_name) = File::Temp::tempfile(
 
 101     'kivitendo-printXXXXXX',
 
 103     DIR    => $::lx_office_conf{paths}->{userspath},
 
 104     UNLINK => ($::lx_office_conf{debug} && $::lx_office_conf{debug}->{keep_temp_files})? 0 : 1,
 
 108   my $input_names = join ' ', String::ShellQuote::shell_quote(@{ $params{file_names} });
 
 109   my $exe         = $::lx_office_conf{applications}->{ghostscript} || 'gs';
 
 110   my $output      = `$exe -dBATCH -dNOPAUSE -q -sDEVICE=pdfwrite -sOutputFile=${temp_name} ${input_names} 2>&1`;
 
 112   die "Executing gs failed: $ERRNO" if !defined $output;
 
 113   die $output                       if $? != 0;
 
 115   return scalar File::Slurp::read_file($temp_name);
 
 119   my ($class, %params) = @_;
 
 121   $params{name} or croak "Missing parameter 'name'";
 
 123   my $path                 = $::instance_conf->get_templates;
 
 124   my $extension            = $params{extension} || "tex";
 
 125   my ($printer, $language) = ('', '');
 
 127   if ($params{printer} || $params{printer_id}) {
 
 128     if ($params{printer} && !ref $params{printer}) {
 
 129       $printer = '_' . $params{printer};
 
 131       $printer = $params{printer} || SL::DB::Printer->new(id => $params{printer_id})->load;
 
 132       $printer = $printer->template_code ? '_' . $printer->template_code : '';
 
 136   if ($params{language} || $params{language_id}) {
 
 137     if ($params{language} && !ref $params{language}) {
 
 138       $language = '_' . $params{language};
 
 140       $language = $params{language} || SL::DB::Language->new(id => $params{language_id})->load;
 
 141       $language = $language->template_code ? '_' . $language->template_code : '';
 
 145   my @template_files = (
 
 146     $params{name} . "${language}${printer}",
 
 147     $params{name} . "${language}",
 
 152   if ($params{email}) {
 
 153     unshift @template_files, (
 
 154       $params{name} . "_email${language}${printer}",
 
 155       $params{name} . "_email${language}",
 
 159   @template_files = map { "${_}.${extension}" } uniq grep { $_ } @template_files;
 
 161   my $template = first { -f ($path . "/$_") } @template_files;
 
 163   return wantarray ? ($template, @template_files) : $template;
 
 175 SL::Helper::CreatePDF - A helper for creating PDFs from template files
 
 179   # Retrieve a sales order from the database and create a PDF for
 
 181   my $order               = SL::DB::Order->new(id => …)->load;
 
 182   my $print_form          = Form->new('');
 
 183   $print_form->{type}     = 'invoice';
 
 184   $print_form->{formname} = 'invoice',
 
 185   $print_form->{format}   = 'pdf',
 
 186   $print_form->{media}    = 'file';
 
 188   $order->flatten_to_form($print_form, format_amounts => 1);
 
 189   $print_form->prepare_for_printing;
 
 191   my $pdf = SL::Helper::CreatePDF->create_pdf(
 
 192     template  => 'sales_order',
 
 193     variables => $print_form,
 
 200 =item C<create_pdf %params>
 
 202 Parses a LaTeX template file, creates a PDF for it and returns either
 
 203 its content or its file name. The recognized parameters are the same
 
 204 as the ones for L</create_parsed_file> with C<format> and
 
 205 C<template_type> being pre-set.
 
 207 =item C<create_parsed_file %params>
 
 209 Parses a template file and returns either its content or its file
 
 210 name. The recognized parameters are:
 
 214 =item * C<template> – mandatory. The template file name relative to
 
 215 the users' templates directory. Must be an existing file name,
 
 216 e.g. one retrieved by L</find_template>.
 
 218 =item * C<variables> – optional hash reference containing variables
 
 219 available to the template.
 
 221 =item * C<return> – optional scalar containing either C<content> (the
 
 222 default) or C<file_name>. If it is set to C<file_name> then the file
 
 223 name of the temporary file containing the PDF is returned, and the
 
 224 caller is responsible for deleting it. Otherwise a scalar containing
 
 225 the PDF itself is returned and all temporary files have already been
 
 226 deleted by L</create_pdf>.
 
 228 =item * C<format> – optional, defaults to C<pdf> and determines the
 
 229 output format. Can be set to C<html> for HTML output if
 
 230 C<template_type> is set to C<HTML> as well.
 
 232 =item * C<template_type> – optional, defaults to C<LaTeX> and
 
 233 determines the template's format. Can be set to C<HTML> for HTML
 
 234 output if C<format> is set to C<html> as well.
 
 238 =item C<find_template %params>
 
 240 Searches the user's templates directory for a template file name to
 
 241 use. The file names considered depend on the parameters; they can
 
 242 contain a template base name and suffixes for email, language and
 
 243 printers. As a fallback the name C<default.$extension> is also
 
 246 The return value depends on the context. In scalar context the
 
 247 template file name that matches the given parameters is returned. It's
 
 248 a file name relative to the user's templates directory. If no template
 
 249 file is found then C<undef> is returned.
 
 251 In list context the first element is the same value as in scalar
 
 252 context. Additionally a list of considered template file names is
 
 255 The recognized parameters are:
 
 259 =item * C<name> – mandatory. The template's file name basis
 
 260 without any additional suffix or extension, e.g. C<sales_quotation>.
 
 262 =item * C<extension> – optional file name extension to use without the
 
 263 dot. Defaults to C<tex>.
 
 265 =item * C<email> – optional flag indicating whether or not the
 
 266 template is to be sent via email. If set to true then template file
 
 267 names containing C<_email> are considered as well.
 
 269 =item * C<language> and C<language_id> – optional parameters
 
 270 indicating the language to be used. C<language> can be either a string
 
 271 containing the language code to use or an instance of
 
 272 C<SL::DB::Language>. C<language_id> can contain the ID of the
 
 273 C<SL::DB:Language> instance to load and use. If given template file
 
 274 names containing C<_language_template_code> are considered as well.
 
 276 =item * C<printer> and C<printer_id> – optional parameters indicating
 
 277 the printer to be used. C<printer> can be either a string containing
 
 278 the printer code to use or an instance of
 
 279 C<SL::DB::Printer>. C<printer_id> can contain the ID of the
 
 280 C<SL::DB:Printer> instance to load and use. If given template file
 
 281 names containing C<_printer_template_code> are considered as well.
 
 285 =item C<merge_pdfs %params>
 
 287 Merges two or more PDFs into a single PDF by using the external
 
 288 application ghostscript.
 
 290 The recognized parameters are:
 
 294 =item * C<file_names> – mandatory array reference containing the file
 
 299 Note that this function relies on the presence of the external
 
 300 application ghostscript. The executable to use is configured via
 
 301 kivitendo's configuration file setting C<application.ghostscript>.
 
 311 Moritz Bunkus E<lt>m.bunkus@linet-services.deE<gt>