Revision 6ba38ffe
Von Martin Helmling martin.helmling@octosoft.eu vor fast 8 Jahren hinzugefügt
SL/Helper/CreatePDF.pm | ||
---|---|---|
6 | 6 |
use Cwd; |
7 | 7 |
use English qw(-no_match_vars); |
8 | 8 |
use File::Slurp (); |
9 |
use File::Spec (); |
|
10 |
use File::Temp (); |
|
9 |
use File::Spec (); |
|
10 |
use File::Temp (); |
|
11 |
use File::Copy qw(move); |
|
11 | 12 |
use List::MoreUtils qw(uniq); |
12 | 13 |
use List::Util qw(first); |
13 | 14 |
use String::ShellQuote (); |
... | ... | |
39 | 40 |
sub create_parsed_file { |
40 | 41 |
my ($class, %params) = @_; |
41 | 42 |
|
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{\.(.+)};
|
|
43 |
my $userspath = $::lx_office_conf{paths}->{userspath}; |
|
44 |
my $vars = $params{variables} || {}; |
|
45 |
my $form = Form->new(''); |
|
46 |
$form->{$_} = $vars->{$_} for keys %{$vars};
|
|
47 |
$form->{format} = lc($params{format} || 'pdf'); |
|
48 |
$form->{cwd} = getcwd(); |
|
49 |
$form->{templates} = $::instance_conf->get_templates; |
|
50 |
$form->{IN} = $params{template}; |
|
51 |
$form->{tmpdir} = $form->{cwd} . '/' . $userspath; |
|
52 |
my $tmpdir = $form->{tmpdir}; |
|
53 |
my ($suffix) = $params{template} =~ m{\.(.+)}; |
|
53 | 54 |
|
54 | 55 |
my ($temp_fh, $tmpfile) = File::Temp::tempfile( |
55 | 56 |
'kivitendo-printXXXXXX', |
56 | 57 |
SUFFIX => ".${suffix}", |
57 | 58 |
DIR => $form->{tmpdir}, |
58 |
UNLINK => ($::lx_office_conf{debug} && $::lx_office_conf{debug}->{keep_temp_files})? 0 : 1, |
|
59 |
UNLINK => |
|
60 |
($::lx_office_conf{debug} && $::lx_office_conf{debug}->{keep_temp_files})? 0 : 1, |
|
59 | 61 |
); |
60 | 62 |
|
61 | 63 |
$form->{tmpfile} = $tmpfile; |
62 | 64 |
(undef, undef, $form->{template_meta}{tmpfile}) = File::Spec->splitpath($tmpfile); |
63 | 65 |
|
64 |
my $parser = SL::Template::create(
|
|
65 |
type => ($params{template_type} || 'LaTeX'),
|
|
66 |
source => $form->{IN}, |
|
67 |
form => $form, |
|
68 |
myconfig => \%::myconfig, |
|
69 |
userspath => $tmpdir, |
|
66 |
my $parser = SL::Template::create( |
|
67 |
type => ($params{template_type} || 'LaTeX'), |
|
68 |
source => $form->{IN},
|
|
69 |
form => $form,
|
|
70 |
myconfig => \%::myconfig,
|
|
71 |
userspath => $tmpdir,
|
|
70 | 72 |
variable_content_types => $params{variable_content_types}, |
71 | 73 |
); |
72 | 74 |
|
... | ... | |
102 | 104 |
return $content; |
103 | 105 |
} |
104 | 106 |
|
107 |
# |
|
108 |
# Alternativen zu pdfinfo wären (aber wesentlich langamer): |
|
109 |
# |
|
110 |
# gs -dBATCH -dNOPAUSE -sDEVICE=pdfwrite -sOutputFile=/dev/null $filename | grep 'Processing pages' |
|
111 |
# my (undef,undef,undef,undef,$pages) = split / +/,$shell_out; |
|
112 |
# |
|
113 |
# gs -dBATCH -dNOPAUSE -q -dNODISPLAY -c "($filename) (r) file runpdfbegin pdfpagecount = quit" |
|
114 |
# $pages=$shell_out; |
|
115 |
# |
|
116 |
|
|
117 |
sub has_odd_pages { |
|
118 |
my ($class, $filename) = @_; |
|
119 |
return 0 unless -f $filename; |
|
120 |
my $shell_out = `pdfinfo $filename | grep 'Pages:'`; |
|
121 |
my ($label, $pages) = split / +/, $shell_out; |
|
122 |
return $pages & 1; |
|
123 |
} |
|
124 |
|
|
105 | 125 |
sub merge_pdfs { |
106 | 126 |
my ($class, %params) = @_; |
127 |
my $filecount = scalar(@{ $params{file_names} }); |
|
107 | 128 |
|
108 |
return scalar(File::Slurp::read_file($params{file_names}->[0])) if scalar(@{ $params{file_names} }) < 2; |
|
129 |
if ($params{inp_content}) { |
|
130 |
return $params{inp_content} if $filecount == 0 && !$params{out_path}; |
|
131 |
} |
|
132 |
elsif ($params{out_path}) { |
|
133 |
return 0 if $filecount == 0; |
|
134 |
if ($filecount == 1) { |
|
135 |
if (!rename($params{file_names}->[0], $params{out_path})) { |
|
136 |
# special filesystem or cross filesystem etc |
|
137 |
move($params{file_names}->[0], $params{out_path}); |
|
138 |
} |
|
139 |
return 1; |
|
140 |
} |
|
141 |
} |
|
142 |
else { |
|
143 |
return '' if $filecount == 0; |
|
144 |
return scalar(File::Slurp::read_file($params{file_names}->[0])) if $filecount == 1; |
|
145 |
} |
|
109 | 146 |
|
110 | 147 |
my ($temp_fh, $temp_name) = File::Temp::tempfile( |
111 | 148 |
'kivitendo-printXXXXXX', |
... | ... | |
115 | 152 |
); |
116 | 153 |
close $temp_fh; |
117 | 154 |
|
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`; |
|
155 |
my $input_names = ''; |
|
156 |
my $hasodd = 0; |
|
157 |
my $emptypage = ''; |
|
158 |
if ($params{bothsided}) { |
|
159 |
$emptypage = $::instance_conf->get_templates . '/emptyPage.pdf'; |
|
160 |
unless (-f $emptypage) { |
|
161 |
$emptypage = ''; |
|
162 |
delete $params{bothsided}; |
|
163 |
} |
|
164 |
} |
|
165 |
if ($params{inp_content}) { |
|
166 |
my ($temp_fh, $inp_name) = File::Temp::tempfile( |
|
167 |
'kivitendo-contentXXXXXX', |
|
168 |
SUFFIX => '.pdf', |
|
169 |
DIR => $::lx_office_conf{paths}->{userspath}, |
|
170 |
UNLINK => ( |
|
171 |
$::lx_office_conf{debug} && $::lx_office_conf{debug}->{keep_temp_files} |
|
172 |
) |
|
173 |
? 0 |
|
174 |
: 1, |
|
175 |
); |
|
176 |
binmode $temp_fh; |
|
177 |
print $temp_fh $params{inp_content}; |
|
178 |
close $temp_fh; |
|
179 |
$input_names = $inp_name . ' '; |
|
180 |
$hasodd = |
|
181 |
($params{bothsided} && __PACKAGE__->has_odd_pages($inp_name) |
|
182 |
? 1 |
|
183 |
: 0 |
|
184 |
); |
|
185 |
} |
|
186 |
foreach (@{ $params{file_names} }) { |
|
187 |
$input_names .= $emptypage . ' ' if $hasodd; |
|
188 |
$input_names .= String::ShellQuote::shell_quote($_) . ' '; |
|
189 |
$hasodd = |
|
190 |
($params{bothsided} && __PACKAGE__->has_odd_pages($_) |
|
191 |
? 1 |
|
192 |
: 0 |
|
193 |
); |
|
194 |
} |
|
195 |
my $exe = $::lx_office_conf{applications}->{ghostscript} || 'gs'; |
|
196 |
my $output = |
|
197 |
`$exe -dBATCH -dNOPAUSE -q -sDEVICE=pdfwrite -sOutputFile=${temp_name} ${input_names} 2>&1`; |
|
121 | 198 |
|
122 | 199 |
die "Executing gs failed: $ERRNO" if !defined $output; |
123 | 200 |
die $output if $? != 0; |
124 | 201 |
|
202 |
if ($params{out_path}) { |
|
203 |
if (!rename($temp_name, $params{out_path})) { |
|
204 |
|
|
205 |
# special filesystem or cross filesystem etc |
|
206 |
move($temp_name, $params{out_path}); |
|
207 |
} |
|
208 |
return 1; |
|
209 |
} |
|
125 | 210 |
return scalar File::Slurp::read_file($temp_name); |
126 | 211 |
} |
127 | 212 |
|
... | ... | |
130 | 215 |
|
131 | 216 |
$params{name} or croak "Missing parameter 'name'"; |
132 | 217 |
|
133 |
my $path = $::instance_conf->get_templates;
|
|
134 |
my $extension = $params{extension} || "tex";
|
|
218 |
my $path = $::instance_conf->get_templates; |
|
219 |
my $extension = $params{extension} || "tex"; |
|
135 | 220 |
my ($printer, $language) = ('', ''); |
136 | 221 |
|
137 | 222 |
if ($params{printer} || $params{printer_id}) { |
138 | 223 |
if ($params{printer} && !ref $params{printer}) { |
139 | 224 |
$printer = '_' . $params{printer}; |
140 |
} else { |
|
225 |
} |
|
226 |
else { |
|
141 | 227 |
$printer = $params{printer} || SL::DB::Printer->new(id => $params{printer_id})->load; |
142 | 228 |
$printer = $printer->template_code ? '_' . $printer->template_code : ''; |
143 | 229 |
} |
... | ... | |
146 | 232 |
if ($params{language} || $params{language_id}) { |
147 | 233 |
if ($params{language} && !ref $params{language}) { |
148 | 234 |
$language = '_' . $params{language}; |
149 |
} else { |
|
235 |
} |
|
236 |
else { |
|
150 | 237 |
$language = $params{language} || SL::DB::Language->new(id => $params{language_id})->load; |
151 | 238 |
$language = $language->template_code ? '_' . $language->template_code : ''; |
152 | 239 |
} |
... | ... | |
160 | 247 |
); |
161 | 248 |
|
162 | 249 |
if ($params{email}) { |
163 |
unshift @template_files, ( |
|
250 |
unshift @template_files, |
|
251 |
( |
|
164 | 252 |
$params{name} . "_email${language}${printer}", |
165 | 253 |
$params{name} . "_email${language}", |
166 |
); |
|
254 |
);
|
|
167 | 255 |
} |
168 | 256 |
|
169 | 257 |
@template_files = map { "${_}.${extension}" } uniq grep { $_ } @template_files; |
... | ... | |
297 | 385 |
Merges two or more PDFs into a single PDF by using the external |
298 | 386 |
application ghostscript. |
299 | 387 |
|
388 |
Normally the function returns the contents of the resulting PDF. |
|
389 |
if The parameter C<out_path> is set the resulting PDF is in this file |
|
390 |
and the return value is 1 if it successful or 0 if not. |
|
391 |
|
|
300 | 392 |
The recognized parameters are: |
301 | 393 |
|
302 | 394 |
=over 2 |
... | ... | |
304 | 396 |
=item * C<file_names> – mandatory array reference containing the file |
305 | 397 |
names to merge. |
306 | 398 |
|
399 |
=item * C<inp_content> – optional, contents of first file to merge with C<file_names>. |
|
400 |
|
|
401 |
=item * C<out_path> – optional, returns not the merged contents but wrote him into this file |
|
402 |
|
|
307 | 403 |
=back |
308 | 404 |
|
309 | 405 |
Note that this function relies on the presence of the external |
Auch abrufbar als: Unified diff
PDF Helper Erweiterungen: bothsided , out_path
merge_pdfs mit weiterem Parameter "out_path"
Statt den Inhalt als Ergebnis zu bekommen, kann nun auch gleich die exitierende Datei zurückgegeben werden
Es kann nun die Seitenzahl der Dokumente ermittelt werden
und ggf (falls param "bothsided" gesetzt) eine leere Seite dazwischengefügt werden