File Coverage

blib/lib/Template/Provider/DBI.pm
Criterion Covered Total %
statement 52 68 76.4
branch 13 34 38.2
condition 10 34 29.4
subroutine 7 8 87.5
pod 1 2 50.0
total 83 146 56.8


line stmt bran cond sub pod time code
1             package Template::Provider::DBI;
2              
3 1     1   287696 use DBI;
  1         2  
  1         63  
4 1     1   964 use DateTime::Format::DBI;
  1         763  
  1         33  
5 1     1   6 use base 'Template::Provider';
  1         7  
  1         1194  
6              
7             our $VERSION = '0.03';
8              
9             sub _init
10             {
11             # check dbi specific params from args, then call super
12             # modified timestamps?
13             # precompiled?
14 1     1   73213 my ($self, $args) = @_;
15              
16 1         14 $self->{$_} = $args->{$_} for keys %$args;
17              
18 1 50 33     11 if($self->{DBI_DBH} && $self->{DBI_DSN})
19             {
20 0         0 return $self->error("DBI:Can't use DBI_DBH and DBI_DSN at the same time");
21             }
22              
23 1 50       5 if($self->{DBI_DSN})
24             {
25 0 0       0 $self->{DBI_DBH} = DBI->connect($self->{DBI_DSN}, $self->{DBI_USER}, $self->{DBI_PASSWD}) or return $self->error("DBI: Failed to connect to $self->{DBI_DSN}, $self->{DBI_USER}, $self->{DBI_PASSWD}, $DBI::errstr");
26             }
27              
28 1   50     8 $self->{DBI_TABLE} ||= 'templates';
29 1   50     6 $self->{DBI_MODIFIEDFIELD} ||= 'modified';
30 1   50     5 $self->{DBI_TMPLFIELD} ||= 'template';
31 1   50     6 $self->{DBI_FILEFIELD} ||= 'filename';
32 1   50     9 $self->{DBI_CURRENTTIME} ||= 'current_timestamp';
33             # $self->{DBI_QUERY} ||= "SELECT $self->{DBI_TMPLFIELD} FROM $self->{DBI_TABLE} WHERE $self->{DBI_FILEFIELD} = ?";
34            
35 1         2 eval {
36 1   33     12 $self->{DBI_DT} ||= DateTime::Format::DBI->new($self->{DBI_DBH}); };
37 1 50       889 if($@)
38             {
39 1         122 warn "DateTime::Format:: for $self->{DBI_DBH}->{Driver}->{Name} not found, no caching supported";
40 1         6 $self->{DBI_DT} = undef;
41 1         2 $self->{DBI_MODIFIEDFIELD} = '';
42             }
43              
44 1         2 my $modified = '';
45 1 50       5 $modified = ", $self->{DBI_MODIFIEDFIELD}" if($self->{DBI_MODIFIEDFIELD});
46 1   33     12 $self->{DBI_QUERY} ||= "SELECT $self->{DBI_TMPLFIELD} $modified FROM $self->{DBI_TABLE} WHERE $self->{DBI_FILEFIELD} = ?";
47 1 50       17 $self->{DBI_STH} = $self->{DBI_DBH}->prepare_cached($self->{DBI_QUERY}) or
48             return $self->error("DBI:Failed to prepare query: $DBI:errstr");
49 1         158 return $self->SUPER::_init();
50             }
51              
52             sub fetch
53             {
54             # called to fetch template by name
55             # return (undef. status_declined) on missing (and on error & tolerant)
56             # return ($error, status_error) on error
57              
58 1     1 1 33885 my ($self, $name) = @_;
59 1         3 my ($data, $error);
60             # we dont do refs or handles:
61 1 50       6 return (undef, Template::Constants::STATUS_DECLINED) if(ref($name));
62              
63             # Check if caching is allowed / file has been cached
64             # my $compiled = $self->_compiled_filename($name);
65 1 50 33     9 if(defined $self->{ SIZE } && $self->{ LOOKUP }->{ $name })
66             {
67 0         0 ($data, $error) = _fetch($name);
68             }
69             else
70             {
71 1         6 ($data, $error) = $self->_load($name);
72 1 50       15 ($data, $error) = $self->_compile($data) unless($error);
73 1 50       35317 $data = $self->_store($name, $data) unless($error);
74             }
75            
76 1         21 return ($data, $error);
77            
78             }
79              
80             sub _load
81             {
82 1     1   3 my ($self, $name) = @_;
83              
84 1         2 my $data = {};
85             # fetch template from db
86 1         144 $self->{DBI_STH}->execute($name);
87 1         26 my ($templ, $modified) = $self->{DBI_STH}->fetchrow_array();
88 1 50       4 return (undef, Template::Constants::STATUS_DECLINED)
89             if(!defined $templ);
90 1 50 33     5 if($modified && exists $self->{DBI_DT})
91             {
92             # No "modified" field used, as we have no DT::Format::X
93 0         0 $data->{time} = $self->convert_timestamp($modified);
94             }
95             else
96             {
97 1         9 $data->{time} = time();
98             }
99 1         2 $data->{load} = time();
100 1         3 $data->{name} = $name;
101 1         6 $data->{text} = $templ;
102              
103 1 50       4 my $err = $DBI::errstr if(!$templ);
104              
105 1         3 return ($data, $err);
106             }
107              
108             ## _store uses stat on the filename, bah
109             ## patch to call _mtime($name) ?
110              
111             sub _modified
112             {
113 1     1   15 my ($self, $name) = @_;
114              
115 1 50       5 if(!defined $self->{DBI_DT})
116             {
117 1         3 return time();
118             }
119              
120 0           my $sth = $self->{DBI_DBH}->prepare_cached(<
121             SELECT $self->{DBI_MODIFIEDFIELD}
122             FROM $self->{DBI_TABLE}
123             WHERE $self->{DBI_FILEFIELD} = ?
124             SQL
125              
126 0           $sth->execute($name);
127 0           my ($result) = $sth->fetchrow_array();
128              
129 0   0       return $self->convert_timestamp($result) || $result;
130              
131             }
132              
133             sub convert_timestamp
134             {
135 0     0 0   my ($self, $timestamp) = @_;
136              
137 0 0         return time() if(!$timestamp);
138 0 0 0       if($self->{DBI_DT} && $self->{DBI_DT}->can('parse_timestamp'))
    0 0        
139             {
140 0           my $dt = $self->{DBI_DT}->parse_timestamp($timestamp);
141 0           return $dt->epoch;
142             }
143             elsif($self->{DBI_DT} && $self->{DBI_DT}->can('format_datetime'))
144             {
145 0           my $dt = $self->{DBI_DT}->parse_datetime($timestamp);
146 0           return $dt->epoch;
147             }
148 0           return 0;
149             }
150              
151              
152             1;
153              
154             __END__