File Coverage

blib/lib/App/dbitemplater.pm
Criterion Covered Total %
statement 17 87 19.5
branch 0 44 0.0
condition 0 12 0.0
subroutine 6 8 75.0
pod 2 2 100.0
total 25 153 16.3


line stmt bran cond sub pod time code
1             package App::dbitemplater;
2              
3 1     1   130612 use 5.006;
  1         5  
4 1     1   6 use strict;
  1         3  
  1         46  
5 1     1   8 use warnings;
  1         2  
  1         62  
6 1     1   793 use Template ();
  1         30983  
  1         44  
7 1     1   696 use File::Slurp qw(write_file);
  1         49245  
  1         87  
8 1     1   1899 use DBI ();
  1         26372  
  1         1343  
9              
10             =head1 NAME
11              
12             App::dbitemplater - A utility for running a SQL query via DBI and using the output in a template.
13              
14             =head1 VERSION
15              
16             Version 0.0.1
17              
18             =cut
19              
20             our $VERSION = '0.0.1';
21              
22             =head1 SYNOPSIS
23              
24             use App::dbitemplater;
25             use YAML::XS;
26             use File::Slurp;
27              
28             $config=Load(read_file('/usr/local/etc/dbitemplater.yaml'));
29              
30             my $dbitemplater = App::dbitemplater->new($config);
31              
32             $dbitemplater->process;
33              
34             =head1 METHODS
35              
36             =head2 new
37              
38             Initiates the object.
39              
40             A hash reference is required. The contents should be the config.
41             See the docs for dbitemplater for the config.
42              
43             =cut
44              
45             sub new {
46 0     0 1   my %args;
47 0 0         if ( defined( $_[1] ) ) {
48 0           %args = %{ $_[1] };
  0            
49             }
50              
51 0           my @possible_args = (
52             'ds', 'user', 'pass', 'output', 'query', 'header',
53             'row', 'footer', 'POST_CHOMP', 'PRE_CHOMP', 'TRIM', 'START_TAG',
54             'END_TAG'
55             );
56 0           my $required_args = {
57             'ds' => 1,
58             'header' => 1,
59             'row' => 1,
60             'footer' => 1,
61             'query' => 1
62             };
63              
64 0           my $self = {
65             'ds' => undef,
66             'user' => undef,
67             'pass' => undef,
68             'output' => undef,
69             'header' => undef,
70             'row' => undef,
71             'footer' => undef,
72             'POST_CHOMP' => undef,
73             'PRE_CHOMP' => undef,
74             'TRIM' => undef,
75             'START_TAG' => undef,
76             'END_TAG' => undef,
77             'config' => \%args,
78             };
79 0           bless $self;
80              
81             # ensure that all required args are present and that any arts that are present have a
82             # ref of ""
83 0           foreach my $item (@possible_args) {
84 0 0 0       if ( defined( $required_args->{$item} ) && !defined( $args{$item} ) ) {
85 0           die( '$args{"' . $item . '"} is not defined and is required' );
86             }
87 0 0 0       if ( defined( $args{$item} ) && ref( $args{$item} ) ne '' ) {
88 0           die( '$args{"' . $item . '"} is defined and ref is "' . ref( $args{$item} ) . '" and not ""' );
89             }
90 0 0         if ( defined( $args{$item} ) ) {
91 0           $self->{$item} = $args{$item};
92             }
93 0 0 0       if ( $item eq 'header' || $item eq 'row' || $item eq 'footer' ) {
      0        
94             # if a slash is found, assume it is a full path
95 0 0         if ( $args{$item} =~ /[\\\/]/ ) {
96 0 0         if ( !-f $args{$item} ) {
97 0           die( '$args{"' . $item . '"}, "' . $args{$item} . '", is not a file or does not exist' );
98             }
99             } else {
100 0           my $full_path = '/usr/local/etc/dbitemplater/templates/' . $item . '/' . $args{$item};
101 0 0         if ( !-f $full_path ) {
102             die( '$args{"'
103             . $item . '"}, "'
104 0           . $args{$item} . '","'
105             . $full_path
106             . '", is not a file or does not exist' );
107             }
108 0           $self->{$item} = $full_path;
109             } ## end else [ if ( $args{$item} =~ /[\\\/]/ ) ]
110             } ## end if ( $item eq 'header' || $item eq 'row' ||...)
111             } ## end foreach my $item (@possible_args)
112              
113 0           return $self;
114             } ## end sub new
115              
116             =head2 process
117              
118             Connects, run the query, and processes the templates.
119              
120             =cut
121              
122             sub process {
123 0     0 1   my $self = $_[0];
124              
125             # initiate TT
126             my $tt = Template->new(
127             {
128             'INCLUDE_PATH' => '/usr/local/etc/dbitemplater/templates',
129             'EVAL_PERL' => 1,
130             'POST_CHOMP' => $self->{'POST_CHOMP'},
131             'PRE_CHOMP' => $self->{'PRE_CHOMP'},
132             'TRIM' => $self->{'TRIM'},
133             'START_TAG' => $self->{'START_TAG'},
134 0           'END_TAG' => $self->{'END_TAG'},
135             'ABSOLUTE' => 1,
136             }
137             );
138              
139             # stores the results of the template
140 0           my $results = '';
141              
142             # will be passed to the template for vars
143 0           my $to_pass_to_template = { 'config' => $self->{config}, };
144             # process the headertemplate
145 0           my $output = '';
146 0           eval {
147 0 0         $tt->process( $self->{'header'}, $to_pass_to_template, \$output )
148             || die $tt->error(), "\n";
149 0           $results = $results . $output;
150             };
151 0 0         if ($@) {
152 0           warn( 'Error processing header template, "' . $self->{'header'} . '"... ' . $@ );
153             }
154              
155             # connect to it
156 0           my $dbh;
157 0 0         eval { $dbh = DBI->connect( $self->{'ds'}, $self->{'user'}, $self->{'pass'} ) or die $DBI::errstr; };
  0            
158 0 0         if ($@) {
159 0           die( 'DBI connect failed... ' . $@ );
160             }
161              
162             # prepare the statement
163 0           my $sth;
164 0 0         eval { $sth = $dbh->prepare( $self->{'query'} ) or die $DBI::errstr; };
  0            
165 0 0         if ($@) {
166 0           die( 'statement prepare failed... ' . $@ );
167             }
168              
169 0 0         eval { $sth->execute or die $DBI::errstr; };
  0            
170 0 0         if ($@) {
171 0           die( 'statement execute failed... ' . $@ );
172             }
173              
174             # fetch each row and process it
175 0           while ( my $row_hash_ref = $sth->fetchrow_hashref ) {
176 0           $to_pass_to_template->{'row'} = $row_hash_ref;
177             # process the template for each row
178 0           my $output = '';
179 0           eval {
180 0 0         $tt->process( $self->{'row'}, $to_pass_to_template, \$output )
181             || die $tt->error(), "\n";
182 0           $results = $results . $output;
183             };
184 0 0         if ($@) {
185 0           warn( 'Error processing header template, "' . $self->{'row'} . '"... ' . $@ );
186             }
187             } ## end while ( my $row_hash_ref = $sth->fetchrow_hashref)
188              
189             # remove the row variable from what is passed to the template
190 0           delete( $to_pass_to_template->{'row'} );
191              
192             # process the footer template
193 0           $output = '';
194 0           eval {
195 0 0         $tt->process( $self->{'footer'}, $to_pass_to_template, \$output )
196             || die $tt->error(), "\n";
197 0           $results = $results . $output;
198             };
199 0 0         if ($@) {
200 0           warn( 'Error processing footer template, "' . $self->{'header'} . '"... ' . $@ );
201             }
202              
203             # handle the output
204 0 0         if ( !defined( $self->{output} ) ) {
205 0           print $results;
206             } else {
207 0           eval { write_file( $self->{'output'}, { atomic => 1 }, $results ); };
  0            
208 0 0         if ($@) {
209 0           die( 'Failed to write results out to "' . $self->{'output'} . '"... ' . $@ );
210             }
211             }
212              
213 0           return 1;
214             } ## end sub process
215              
216             =head1 AUTHOR
217              
218             Zane C. Bowers-Hadley, C<< >>
219              
220             =head1 BUGS
221              
222             Please report any bugs or feature requests to C, or through
223             the web interface at L. I will be notified, and then you'll
224             automatically be notified of progress on your bug as I make changes.
225              
226              
227              
228              
229             =head1 SUPPORT
230              
231             You can find documentation for this module with the perldoc command.
232              
233             perldoc App::dbitemplater
234              
235              
236             You can also look for information at:
237              
238             =over 4
239              
240             =item * RT: CPAN's request tracker (report bugs here)
241              
242             L
243              
244             =item * CPAN Ratings
245              
246             L
247              
248             =item * Search CPAN
249              
250             L
251              
252             =back
253              
254              
255             =head1 ACKNOWLEDGEMENTS
256              
257              
258             =head1 LICENSE AND COPYRIGHT
259              
260             This software is Copyright (c) 2025 by Zane C. Bowers-Hadley.
261              
262             This is free software, licensed under:
263              
264             The GNU General Public License, Version 3, June 2007
265              
266              
267             =cut
268              
269             1; # End of App::dbitemplater