File Coverage

blib/lib/Catmandu/Exporter/Template.pm
Criterion Covered Total %
statement 40 43 93.0
branch 5 8 62.5
condition 3 4 75.0
subroutine 11 11 100.0
pod 0 1 0.0
total 59 67 88.0


line stmt bran cond sub pod time code
1             package Catmandu::Exporter::Template;
2              
3 3     3   244691 use Catmandu::Sane;
  3         564725  
  3         26  
4 3     3   1030 use Catmandu::Util qw(is_string);
  3         15  
  3         566  
5 3     3   1665 use Catmandu;
  3         356735  
  3         19  
6 3     3   2362 use Template;
  3         65523  
  3         146  
7 3     3   1615 use Storable qw(freeze);
  3         10456  
  3         245  
8 3     3   33 use Moo;
  3         9  
  3         35  
9 3     3   1592 use namespace::clean;
  3         10  
  3         38  
10              
11             our $VERSION = '0.12';
12              
13             with 'Catmandu::Exporter';
14              
15             my $TT_INSTANCES = {};
16              
17             my $XML_DECLARATION = qq(<?xml version="1.0" encoding="UTF-8"?>\n);
18              
19             my $ADD_TT_EXT = sub {
20             my $tmpl = $_[0];
21             is_string($tmpl) && $tmpl !~ /\.\w{2,4}$/ ? "$tmpl.tt" : $tmpl;
22             };
23              
24             my $OWN_OPTS = {
25             map {($_ => 1)}
26             qw(
27             log_category
28             autocommit
29             count
30             file
31             fh
32             xml
33             template
34             template_before
35             template_after
36             )
37             };
38              
39             has xml => (is => 'ro');
40             has template_before => (is => 'ro', coerce => $ADD_TT_EXT);
41             has template => (is => 'ro', coerce => $ADD_TT_EXT, required => 1);
42             has template_after => (is => 'ro', coerce => $ADD_TT_EXT);
43             has _tt_opts => (is => 'lazy', init_arg => undef);
44             has _tt => (is => 'lazy', init_arg => undef);
45             has _before_done => (is => 'rw', init_arg => undef);
46              
47             sub BUILD {
48 10     10 0 158 my ($self, $opts) = @_;
49 10         225 my $tt_opts = $self->_tt_opts;
50 10         80429 for my $key (keys %$opts) {
51 30 100       155 $tt_opts->{uc $key} = $opts->{$key} unless $OWN_OPTS->{$key};
52             }
53             }
54              
55             sub _build__tt_opts {
56             +{
57 10     10   163 ENCODING => 'utf8',
58             ABSOLUTE => 1,
59             RELATIVE => 1,
60             ANYCASE => 0,
61             INCLUDE_PATH => Catmandu->root,
62             };
63             }
64              
65             sub _build__tt {
66 9     9   148 my ($self) = @_;
67 9         165 my $opts = $self->_tt_opts;
68              
69 9         73 my $instance_key = do {
70 9         22 local $Storable::canonical = 1;
71 9         65 freeze($opts);
72             };
73 9 100       686 if (my $instance = $TT_INSTANCES->{$instance_key}) {
74 4         109 return $instance;
75             }
76              
77 5   50     41 my $vars = $opts->{VARIABLES} ||= {};
78 5         26 $vars->{_root} = Catmandu->root;
79 5         102 $vars->{_config} = Catmandu->config;
80 5         81 local $Template::Stash::PRIVATE = 0;
81 5         60 $TT_INSTANCES->{$instance_key} = Template->new(%$opts);
82             }
83              
84             sub _process {
85 7     7   21 my ($self, $tmpl, $data) = @_;
86 7 50 100     162 unless ($self->_tt->process($tmpl, $data || {}, $self->fh)) {
87 0           my $msg = "Template error";
88 0 0         $msg .= ": " . $self->_tt->error->info if $self->_tt->error;
89 0           Catmandu::Error->throw($msg);
90             }
91             }
92              
93             sub add {
94             my ($self, $data) = @_;
95             unless ($self->_before_done) {
96             $self->fh->print($XML_DECLARATION) if $self->xml;
97             $self->_process($self->template_before) if $self->template_before;
98             $self->_before_done(1);
99             }
100             $self->_process($self->template, $data);
101             }
102              
103             sub commit {
104             my ($self) = @_;
105             $self->_process($self->template_after) if $self->template_after;
106             }
107              
108             =head1 NAME
109              
110             Catmandu::Exporter::Template - a TT2 Template exporter in Catmandu style
111              
112             =head1 SYNOPSIS
113              
114             # From the command line
115             echo '{"colors":["red","green","blue"]}' |
116             catmandu convert JSON to Template --template `pwd`/xml.tt
117              
118             where xml.tt like:
119              
120             <colors>
121             [% FOREACH c IN colors %]
122             <color>[% c %]</color>
123             [% END %]
124             </colors>
125              
126             # From perl
127             use Catmandu::Exporter::Template;
128              
129             my $exporter = Catmandu::Exporter::Template->new(
130             fix => 'myfix.txt'
131             xml => 1,
132             template_before => '<path>/header.xml' ,
133             template => '<path>/record.xml' ,
134             template_after => '<path>/footer.xml' ,
135             );
136              
137             $exporter->add_many($arrayref);
138             $exporter->add_many($iterator);
139             $exporter->add_many(sub { });
140              
141             $exporter->add($hashref);
142              
143             $exporter->commit; # trigger the template_after
144              
145             printf "exported %d objects\n" , $exporter->count;
146              
147             =head1 DESCRIPTION
148              
149             This L<Catmandu::Exporter> can be used to export records using
150             L<Template Toolkit|Template::Manual>. If you are new to Catmandu
151             see L<Catmandu::Tutorial>.
152              
153             =head1 CONFIGURATION
154              
155             =over
156              
157             =item template
158              
159             Required. Must contain path to the template.
160              
161             =item xml
162              
163             Optional. Value: 0 or 1. Prepends xml header to the template.
164              
165             =item template_before
166              
167             Optional. Prepend output to the export.
168              
169             =item template_after
170              
171             Optional. Append output to the export.
172              
173             =item fix
174              
175             Optional. Apply Catmandu fixes while exporting.
176              
177             =item [Template Toolkit configuration options]
178              
179             You can also pass all Template Toolkit configuration options.
180              
181             =back
182              
183             =head1 SEE ALSO
184              
185             L<Catmandu::Exporter>, L<Template>
186              
187             =cut
188              
189             1;