File Coverage

blib/lib/EB/Report/GenBase.pm
Criterion Covered Total %
statement 18 135 13.3
branch 0 74 0.0
condition 0 26 0.0
subroutine 6 14 42.8
pod 0 6 0.0
total 24 255 9.4


line stmt bran cond sub pod time code
1             #! perl -- -*- coding: utf-8 -*-
2              
3 1     1   7 use utf8;
  1         4  
  1         9  
4              
5             # Author : Johan Vromans
6             # Created On : Sat Oct 8 16:40:43 2005
7             # Last Modified By: Johan Vromans
8             # Last Modified On: Thu Aug 31 10:01:19 2017
9             # Update Count : 179
10             # Status : Unknown, Use with caution!
11              
12             package main;
13              
14             our $cfg;
15             our $dbh;
16              
17             package EB::Report::GenBase;
18              
19 1     1   61 use strict;
  1         1  
  1         23  
20 1     1   4 use EB;
  1         2  
  1         214  
21              
22 1     1   592 use IO::File;
  1         963  
  1         110  
23 1     1   9 use EB::Format;
  1         2  
  1         1783  
24              
25             sub new {
26 0     0 0   my ($class, $opts) = @_;
27 0   0       $class = ref($class) || $class;
28 0           my $self = { %$opts };
29 0           bless $self => $class;
30             }
31              
32             # API.
33 0     0     sub _oops { warn("?Package ".ref($_[0])." did not implement '$_[1]' method\n") }
34 0     0 0   sub start { shift->_oops('start') }
35 0     0 0   sub outline { shift->_oops('outline') }
36 0     0 0   sub finish { shift->_oops('finish') }
37              
38             # Class methods
39              
40             sub backend {
41 0     0 0   my (undef, $self, $opts) = @_;
42              
43 0           my %extmap = ( txt => "text", htm => "html" );
44              
45 0           my $gen;
46              
47             # Short options, like --html.
48 0           for ( qw(html csv text) ) {
49 0 0         $gen = $_ if $opts->{$_};
50             }
51              
52             # Override by explicit --gen-XXX option(s).
53 0           foreach ( keys(%$opts) ) {
54 0 0         next unless /^gen-(.*)$/;
55 0           $gen = $1;
56             }
57              
58             # Override by explicit --generate option(s).
59 0 0         $gen = $opts->{generate} if $opts->{generate};
60              
61             # Infer from filename extension.
62 0           my $t;
63 0 0 0       if ( !defined($gen) && ($t = $opts->{output}) && $t =~ /\.([^.]+)$/ ) {
      0        
64 0           my $ext = lc($1);
65 0   0       $ext = $extmap{$ext} || $ext;
66 0           $gen = $ext;
67             }
68              
69             # Fallback to text.
70 0   0       $gen ||= "text";
71              
72             # Build class and package name. Last chance to override...
73 0   0       my $class = $opts->{backend} || (ref($self)||$self) . "::" . ucfirst($gen);
74 0           my $pkg = $class;
75 0           $pkg =~ s;::;/;g;;
76 0           $pkg .= ".pm";
77              
78             # Try to load backend. Gives user the opportunity to override.
79             eval {
80 0           local $SIG{__WARN__};
81 0           local $SIG{__DIE__};
82 0           require $pkg;
83 0 0         } unless $ENV{AUTOMATED_TESTING};
84 0 0         if ( ! _loaded($class) ) {
85 0           my $err = $@;
86 0 0         if ( $err =~ /^can't locate /i ) {
87 0           $err = _T("De uitvoer-backend kon niet worden gevonden");
88             }
89 0           die("?".__x("Uitvoer in de vorm {gen} is niet mogelijk: {reason}",
90             gen => $gen, reason => $err)."\n");
91             }
92 0           my $be = $class->new($opts);
93              
94             # Handle output redirection.
95 0 0 0       if ( $opts->{output} && $opts->{output} ne '-' ) {
    0          
96             $be->{fh} = IO::File->new($opts->{output}, "w")
97             or die("?".__x("Fout tijdens aanmaken {file}: {err}",
98 0 0         file => $opts->{output}, err => $!)."\n");
99             }
100             elsif ( fileno(STDOUT) > 0 ) {
101             # Normal file.
102 0           $be->{fh} = IO::File->new_from_fd(fileno(STDOUT), "w");
103             }
104             else {
105             # In-memory.
106 0           $be->{fh} = bless \*STDOUT , 'IO::Handle';
107             }
108 0           binmode($be->{fh}, ":encoding(utf8)");
109              
110             # Handle pagesize.
111 0 0         $be->{fh}->format_lines_per_page($be->{page} = defined($opts->{page}) ? $opts->{page} : 999999);
112              
113             # Get real (or fake) current date, and adjust periode end if needed.
114 0           $be->{now} = iso8601date();
115 0 0         if ( my $t = $cfg->val(qw(internal now), 0) ) {
116 0 0         $be->{now} = $t if $be->{now} gt $t;
117             }
118              
119             # Date/Per.
120 0 0 0       if ( $opts->{per} ) {
    0          
    0          
121 0 0         die(_T("--per sluit --periode uit")."\n") if $opts->{periode};
122 0 0         die(_T("--per sluit --boekjaar uit")."\n") if defined $opts->{boekjaar};
123             $be->{periode} = [ $be->{per_begin} = $dbh->adm("begin"),
124 0           $be->{per_end} = $opts->{per} ];
125 0           $be->{periodex} = 1;
126             }
127             elsif ( $opts->{periode} ) {
128 0 0         die(_T("--periode sluit --boekjaar uit")."\n") if defined $opts->{boekjaar};
129 0           $be->{periode} = $opts->{periode};
130 0           $be->{per_begin} = $opts->{periode}->[0];
131 0           $be->{per_end} = $opts->{periode}->[1];
132 0           $be->{periodex} = 2;
133             }
134             elsif ( defined($opts->{boekjaar}) || defined($opts->{d_boekjaar}) ) {
135 0           my $bky = $opts->{boekjaar};
136 0 0         $bky = $opts->{d_boekjaar} unless defined $bky;
137 0           my $rr = $dbh->do("SELECT bky_begin, bky_end".
138             " FROM Boekjaren".
139             " WHERE bky_code = ?", $bky);
140 0 0         die("?",__x("Onbekend boekjaar: {bky}", bky => $bky)."\n"), return unless $rr;
141 0           my ($begin, $end) = @$rr;
142             $be->{periode} = [ $be->{per_begin} = $begin,
143 0           $be->{per_end} = $end ];
144 0           $be->{periodex} = 3;
145 0           $be->{boekjaar} = $bky;
146             }
147             else {
148             $be->{periode} = [ $be->{per_begin} = $dbh->adm("begin"),
149 0           $be->{per_end} = $dbh->adm("end") ];
150 0           $be->{periodex} = 0;
151             }
152              
153 0 0         if ( $be->{per_end} gt $be->{now} ) {
154             warn("!".__x("Datum {per} valt na de huidige datum {now}",
155             per => datefmt_full($be->{per_end}),
156 0           now => datefmt_full($be->{now}))."\n")
157             if 0;
158             $be->{periode}->[1] = $be->{per_end} = $be->{now}
159 0           if 0;
160             }
161              
162             # Sanity.
163 0           my $opendate = $dbh->do("SELECT min(bky_begin) FROM Boekjaren WHERE NOT bky_code = ?",
164             BKY_PREVIOUS)->[0];
165              
166 0 0         if ( $be->{per_begin} gt $be->{now} ) {
167             die("?".__x("Periode begint {from}, dit is na de huidige datum {now}",
168             from => datefmt_full($be->{per_begin}),
169 0           now => datefmt_full($be->{now}))."\n");
170             }
171 0 0         if ( $be->{per_begin} lt $opendate ) {
172             die("?".__x("Datum {per} valt vóór het begin van de administratie {begin}",
173 0           per => datefmt_full($be->{per_begin}),
174             begin => datefmt_full($opendate))."\n");
175             }
176 0 0         if ( $be->{per_end} lt $opendate ) {
177             die("?".__x("Datum {per} valt vóór het begin van de administratie {begin}",
178 0           per => datefmt_full($be->{per_end}),
179             begin => datefmt_full($opendate))."\n");
180             }
181              
182 0           $be->{_cssdir} = $cfg->val(qw(html cssdir), undef);
183 0 0         $be->{_cssdir} =~ s;/*$;/; if defined $be->{_cssdir};
184 0 0         $be->{_style} = $opts->{style} if $opts->{style};
185 0 0         $be->{_title0} = $opts->{title} if $opts->{title};
186              
187             # Return instance.
188 0           $be;
189             }
190              
191             my %bec;
192              
193             sub backend_options {
194 0     0 0   my (undef, $self, $opts) = @_;
195              
196 0   0       my $package = ref($self) || $self;
197 0           my $pkg = $package;
198 0           $pkg =~ s;::;/;g;;
199 0 0         return @{$bec{$pkg}} if $bec{$pkg};
  0            
200              
201             # Some standard backends may be included in the coding ...
202 0           my %be;
203 0           foreach my $std ( qw(text html csv) ) {
204 0 0         $be{$std} = 1 if _loaded($package . "::" . ucfirst($std));
205             }
206              
207             #### FIXME: options dest is uncontrollable!!!!
208             #### DO NOT TRANSLATE UNTIL FIXED !!!!
209              
210 0           my @opts = ( __xt("cmo:report:output")."=s",
211             __xt("cmo:report:page")."=i" );
212              
213 0 0         if ( $App::Packager::PACKAGED ) {
214 0           $be{wxhtml}++;
215 0 0         unless ( $be{wxhtml} ) {
216             # Ignored, but forces the packager to include these modules.
217 0           require EB::Report::BTWAangifte::Wxhtml;
218 0           require EB::Report::Balres::Wxhtml;
219 0           require EB::Report::Debcrd::Wxhtml;
220 0           require EB::Report::Grootboek::Wxhtml;
221 0           require EB::Report::Journal::Wxhtml;
222 0           require EB::Report::Open::Wxhtml;
223 0           require EB::Report::Proof::Wxhtml;
224             }
225             }
226             else {
227             # Find files.
228 0           foreach my $lib ( @INC ) {
229 0           my @files = glob("$lib/$pkg/*.pm");
230 0 0         next unless @files;
231             # warn("=> be_opt: found ", scalar(@files), " files in $lib/$pkg\n");
232 0           foreach ( @files ) {
233 0 0         next unless m;/([^/]+)\.pm$;;
234             # Actually, we should check whether the class implements the
235             # GenBase API, but we can't do that without preloading all
236             # backends.
237 0           $be{lc($1)}++;
238             }
239             }
240             }
241              
242             # Short --XXX for known backends.
243 0           foreach ( qw(html csv text) ) {
244 0 0         push(@opts, $_) if $be{$_};
245             }
246             push(@opts,
247             __xt("cmo:report:style")."=s",
248 0 0         __xt("cmo:report:title|titel")."=s") if $be{html};
249              
250             # Explicit --gen-XXX for all backends.
251 0           push(@opts, map { +"gen-$_"} keys %be);
  0            
252             # Cache.
253 0           $bec{$pkg} = [@opts];
254              
255 0           @opts; # better be list context
256             }
257              
258             # Helper.
259              
260             sub _loaded {
261 0     0     my $class = shift;
262 1     1   16 no strict "refs";
  1         2  
  1         85  
263 0 0         %{$class . "::"} ? 1 : 0;
  0            
264             }
265             1;