1 package SL::Helper::CreatePDF;
7 use English qw(-no_match_vars);
11 use List::MoreUtils qw(uniq);
12 use List::Util qw(first);
13 use String::ShellQuote ();
21 use SL::Template::LaTeX;
23 use Exporter 'import';
24 our @EXPORT_OK = qw(create_pdf merge_pdfs find_template);
30 my ($class, %params) = @_;
32 return __PACKAGE__->create_parsed_file(
34 template_type => 'LaTeX',
39 sub create_parsed_file {
40 my ($class, %params) = @_;
42 my $userspath = $::lx_office_conf{paths}->{userspath};
43 my $vars = $params{variables} || {};
44 my $form = Form->new('');
45 $form->{$_} = $vars->{$_} for keys %{ $vars };
46 $form->{format} = lc($params{format} || 'pdf');
47 $form->{cwd} = getcwd();
48 $form->{templates} = $::instance_conf->get_templates;
49 $form->{IN} = $params{template};
50 $form->{tmpdir} = $form->{cwd} . '/' . $userspath;
51 my $tmpdir = $form->{tmpdir};
52 my ($suffix) = $params{template} =~ m{\.(.+)};
54 my ($temp_fh, $tmpfile) = File::Temp::tempfile(
55 'kivitendo-printXXXXXX',
56 SUFFIX => ".${suffix}",
57 DIR => $form->{tmpdir},
58 UNLINK => ($::lx_office_conf{debug} && $::lx_office_conf{debug}->{keep_temp_files})? 0 : 1,
61 $form->{tmpfile} = $tmpfile;
62 (undef, undef, $form->{template_meta}{tmpfile}) = File::Spec->splitpath($tmpfile);
64 my $parser = SL::Template::create(
65 type => ($params{template_type} || 'LaTeX'),
66 source => $form->{IN},
68 myconfig => \%::myconfig,
70 variable_content_types => $params{variable_content_types},
73 my $result = $parser->parse($temp_fh);
80 die $parser->get_error;
83 # SL::Template:** modify $form->{tmpfile} by removing its
84 # $form->{userspath} prefix. They also store the final file's actual
85 # file name in $form->{tmpfile} – but it is now relative to
86 # $form->{userspath}. Other modules return the full file name…
87 my ($volume, $directory, $file_name) = File::Spec->splitpath($form->{tmpfile});
88 my $full_file_name = File::Spec->catfile($tmpdir, $file_name);
89 if (($params{return} || 'content') eq 'file_name') {
90 my $new_name = File::Spec->catfile($tmpdir, 'keep-' . $form->{tmpfile});
91 rename $full_file_name, $new_name;
98 my $content = File::Slurp::read_file($full_file_name);
106 my ($class, %params) = @_;
108 return scalar(File::Slurp::read_file($params{file_names}->[0])) if scalar(@{ $params{file_names} }) < 2;
110 my ($temp_fh, $temp_name) = File::Temp::tempfile(
111 'kivitendo-printXXXXXX',
113 DIR => $::lx_office_conf{paths}->{userspath},
114 UNLINK => ($::lx_office_conf{debug} && $::lx_office_conf{debug}->{keep_temp_files})? 0 : 1,
118 my $input_names = join ' ', String::ShellQuote::shell_quote(@{ $params{file_names} });
119 my $exe = $::lx_office_conf{applications}->{ghostscript} || 'gs';
120 my $output = `$exe -dBATCH -dNOPAUSE -q -sDEVICE=pdfwrite -sOutputFile=${temp_name} ${input_names} 2>&1`;
122 die "Executing gs failed: $ERRNO" if !defined $output;
123 die $output if $? != 0;
125 return scalar File::Slurp::read_file($temp_name);
129 my ($class, %params) = @_;
131 $params{name} or croak "Missing parameter 'name'";
133 my $path = $::instance_conf->get_templates;
134 my $extension = $params{extension} || "tex";
135 my ($printer, $language) = ('', '');
137 if ($params{printer} || $params{printer_id}) {
138 if ($params{printer} && !ref $params{printer}) {
139 $printer = '_' . $params{printer};
141 $printer = $params{printer} || SL::DB::Printer->new(id => $params{printer_id})->load;
142 $printer = $printer->template_code ? '_' . $printer->template_code : '';
146 if ($params{language} || $params{language_id}) {
147 if ($params{language} && !ref $params{language}) {
148 $language = '_' . $params{language};
150 $language = $params{language} || SL::DB::Language->new(id => $params{language_id})->load;
151 $language = $language->template_code ? '_' . $language->template_code : '';
155 my @template_files = (
156 $params{name} . "${language}${printer}",
157 $params{name} . "${language}",
162 if ($params{email}) {
163 unshift @template_files, (
164 $params{name} . "_email${language}${printer}",
165 $params{name} . "_email${language}",
169 @template_files = map { "${_}.${extension}" } uniq grep { $_ } @template_files;
171 my $template = first { -f ($path . "/$_") } @template_files;
173 return wantarray ? ($template, @template_files) : $template;
185 SL::Helper::CreatePDF - A helper for creating PDFs from template files
189 # Retrieve a sales order from the database and create a PDF for
191 my $order = SL::DB::Order->new(id => …)->load;
192 my $print_form = Form->new('');
193 $print_form->{type} = 'invoice';
194 $print_form->{formname} = 'invoice',
195 $print_form->{format} = 'pdf',
196 $print_form->{media} = 'file';
198 $order->flatten_to_form($print_form, format_amounts => 1);
199 $print_form->prepare_for_printing;
201 my $pdf = SL::Helper::CreatePDF->create_pdf(
202 template => 'sales_order',
203 variables => $print_form,
210 =item C<create_pdf %params>
212 Parses a LaTeX template file, creates a PDF for it and returns either
213 its content or its file name. The recognized parameters are the same
214 as the ones for L</create_parsed_file> with C<format> and
215 C<template_type> being pre-set.
217 =item C<create_parsed_file %params>
219 Parses a template file and returns either its content or its file
220 name. The recognized parameters are:
224 =item * C<template> – mandatory. The template file name relative to
225 the users' templates directory. Must be an existing file name,
226 e.g. one retrieved by L</find_template>.
228 =item * C<variables> – optional hash reference containing variables
229 available to the template.
231 =item * C<return> – optional scalar containing either C<content> (the
232 default) or C<file_name>. If it is set to C<file_name> then the file
233 name of the temporary file containing the PDF is returned, and the
234 caller is responsible for deleting it. Otherwise a scalar containing
235 the PDF itself is returned and all temporary files have already been
236 deleted by L</create_pdf>.
238 =item * C<format> – optional, defaults to C<pdf> and determines the
239 output format. Can be set to C<html> for HTML output if
240 C<template_type> is set to C<HTML> as well.
242 =item * C<template_type> – optional, defaults to C<LaTeX> and
243 determines the template's format. Can be set to C<HTML> for HTML
244 output if C<format> is set to C<html> as well.
248 =item C<find_template %params>
250 Searches the user's templates directory for a template file name to
251 use. The file names considered depend on the parameters; they can
252 contain a template base name and suffixes for email, language and
253 printers. As a fallback the name C<default.$extension> is also
256 The return value depends on the context. In scalar context the
257 template file name that matches the given parameters is returned. It's
258 a file name relative to the user's templates directory. If no template
259 file is found then C<undef> is returned.
261 In list context the first element is the same value as in scalar
262 context. Additionally a list of considered template file names is
265 The recognized parameters are:
269 =item * C<name> – mandatory. The template's file name basis
270 without any additional suffix or extension, e.g. C<sales_quotation>.
272 =item * C<extension> – optional file name extension to use without the
273 dot. Defaults to C<tex>.
275 =item * C<email> – optional flag indicating whether or not the
276 template is to be sent via email. If set to true then template file
277 names containing C<_email> are considered as well.
279 =item * C<language> and C<language_id> – optional parameters
280 indicating the language to be used. C<language> can be either a string
281 containing the language code to use or an instance of
282 C<SL::DB::Language>. C<language_id> can contain the ID of the
283 C<SL::DB:Language> instance to load and use. If given template file
284 names containing C<_language_template_code> are considered as well.
286 =item * C<printer> and C<printer_id> – optional parameters indicating
287 the printer to be used. C<printer> can be either a string containing
288 the printer code to use or an instance of
289 C<SL::DB::Printer>. C<printer_id> can contain the ID of the
290 C<SL::DB:Printer> instance to load and use. If given template file
291 names containing C<_printer_template_code> are considered as well.
295 =item C<merge_pdfs %params>
297 Merges two or more PDFs into a single PDF by using the external
298 application ghostscript.
300 The recognized parameters are:
304 =item * C<file_names> – mandatory array reference containing the file
309 Note that this function relies on the presence of the external
310 application ghostscript. The executable to use is configured via
311 kivitendo's configuration file setting C<application.ghostscript>.
321 Moritz Bunkus E<lt>m.bunkus@linet-services.deE<gt>