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   210157 use Catmandu::Sane;
  3         579492  
  3         25  
4 3     3   1002 use Catmandu::Util qw(is_string);
  3         7  
  3         151  
5 3     3   1537 use Catmandu;
  3         345366  
  3         15  
6 3     3   2275 use Template;
  3         57086  
  3         113  
7 3     3   1890 use Storable qw(freeze);
  3         9474  
  3         191  
8 3     3   25 use Moo;
  3         8  
  3         25  
9 3     3   1264 use namespace::clean;
  3         17  
  3         23  
10              
11             our $VERSION = '0.13';
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 15     15 0 172 my ($self, $opts) = @_;
49 15         254 my $tt_opts = $self->_tt_opts;
50 15         82759 for my $key (keys %$opts) {
51 46 100       209 $tt_opts->{uc $key} = $opts->{$key} unless $OWN_OPTS->{$key};
52             }
53             }
54              
55             sub _build__tt_opts {
56             +{
57 15     15   213 ENCODING => 'utf8',
58             ABSOLUTE => 1,
59             RELATIVE => 1,
60             ANYCASE => 0,
61             INCLUDE_PATH => Catmandu->root,
62             };
63             }
64              
65             sub _build__tt {
66 15     15   678 my ($self) = @_;
67 15         229 my $opts = $self->_tt_opts;
68              
69 15         107 my $instance_key = do {
70 15         27 local $Storable::canonical = 1;
71 15         53 freeze($opts);
72             };
73 15 100       999 if (my $instance = $TT_INSTANCES->{$instance_key}) {
74 8         188 return $instance;
75             }
76              
77 7   50     53 my $vars = $opts->{VARIABLES} ||= {};
78 7         37 $vars->{_root} = Catmandu->root;
79 7         133 $vars->{_config} = Catmandu->config;
80 7         93 local $Template::Stash::PRIVATE = 0;
81 7         79 $TT_INSTANCES->{$instance_key} = Template->new({%$opts});
82             }
83              
84             sub _process {
85 13     13   36 my ($self, $tmpl, $data) = @_;
86 13 50 100     244 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             unless ($self->_before_done) {
106             $self->fh->print($XML_DECLARATION) if $self->xml;
107             $self->_process($self->template_before) if $self->template_before;
108             $self->_before_done(1);
109             }
110             $self->_process($self->template_after) if $self->template_after;
111             }
112              
113             =head1 NAME
114              
115             Catmandu::Exporter::Template - a TT2 Template exporter in Catmandu style
116              
117             =head1 SYNOPSIS
118              
119             # From the command line
120             echo '{"colors":["red","green","blue"]}' |
121             catmandu convert JSON to Template --template `pwd`/xml.tt
122              
123             where xml.tt like:
124              
125             <colors>
126             [% FOREACH c IN colors %]
127             <color>[% c %]</color>
128             [% END %]
129             </colors>
130              
131             # From perl
132             use Catmandu::Exporter::Template;
133              
134             my $exporter = Catmandu::Exporter::Template->new(
135             fix => 'myfix.txt'
136             xml => 1,
137             template_before => '<path>/header.xml' ,
138             template => '<path>/record.xml' ,
139             template_after => '<path>/footer.xml' ,
140             );
141              
142             $exporter->add_many($arrayref);
143             $exporter->add_many($iterator);
144             $exporter->add_many(sub { });
145              
146             $exporter->add($hashref);
147              
148             $exporter->commit; # trigger the template_after
149              
150             printf "exported %d objects\n" , $exporter->count;
151              
152             =head1 DESCRIPTION
153              
154             This L<Catmandu::Exporter> can be used to export records using
155             L<Template Toolkit|Template::Manual>. If you are new to Catmandu
156             see L<Catmandu::Tutorial>.
157              
158             =head1 CONFIGURATION
159              
160             =over
161              
162             =item template
163              
164             Required. Must contain path to the template.
165              
166             =item xml
167              
168             Optional. Value: 0 or 1. Prepends xml header to the template.
169              
170             =item template_before
171              
172             Optional. Prepend output to the export.
173              
174             =item template_after
175              
176             Optional. Append output to the export.
177              
178             =item fix
179              
180             Optional. Apply Catmandu fixes while exporting.
181              
182             =item [Template Toolkit configuration options]
183              
184             You can also pass all Template Toolkit configuration options.
185              
186             =back
187              
188             =head1 SEE ALSO
189              
190             L<Catmandu::Exporter>, L<Template>
191              
192             =cut
193              
194             1;