File Coverage

blib/lib/Mojolicious/Plugin/TtRenderer/Engine.pm
Criterion Covered Total %
statement 134 136 98.5
branch 41 54 75.9
condition 10 21 47.6
subroutine 28 28 100.0
pod 1 1 100.0
total 214 240 89.1


line stmt bran cond sub pod time code
1             package Mojolicious::Plugin::TtRenderer::Engine;
2              
3 9     9   724515 use warnings;
  9         31  
  9         324  
4 9     9   51 use strict;
  9         18  
  9         173  
5 9     9   183 use 5.016;
  9         44  
6 9     9   47 use base 'Mojo::Base';
  9         21  
  9         922  
7 9     9   59 use Carp ();
  9         20  
  9         172  
8 9     9   65 use File::Spec ();
  9         21  
  9         221  
9 9     9   565 use Mojo::ByteStream 'b';
  9         4517  
  9         592  
10 9     9   5216 use Template ();
  9         181972  
  9         307  
11 9     9   166 use Cwd qw/abs_path/;
  9         23  
  9         529  
12 9     9   63 use Scalar::Util 'weaken';
  9         24  
  9         391  
13 9     9   768 use POSIX ':errno_h';
  9         7432  
  9         87  
14              
15             # ABSTRACT: Template Toolkit renderer for Mojolicious
16             our $VERSION = '1.62'; # VERSION
17              
18             __PACKAGE__->attr('tt');
19              
20             sub build {
21 8     8 1 988 my $self = shift->SUPER::new(@_);
22 8         137 weaken($self->{app});
23 8         37 $self->_init(@_);
24 36     36   586386 sub { $self->_render(@_) }
25 8         69 }
26              
27             sub _init {
28 8     8   16 my $self = shift;
29 8         29 my %args = @_;
30              
31             #$Template::Parser::DEBUG = 1;
32              
33 8         19 my $dir;
34 8   66     70 my $app = delete $args{mojo} || delete $args{app};
35 8 100       33 if($dir=$args{cache_dir}) {
36              
37 1 50 33     7 if($app && substr($dir,0,1) ne '/') {
38 1         8 $dir=$app->home->rel_file($dir);
39             }
40             }
41              
42             # TODO
43             # take and process options :-)
44              
45 8 50       125 my @renderer_paths = $app ? map { abs_path($_) } grep { -d $_ } @{ $app->renderer->paths } : ();
  8         484  
  9         709  
  8         63  
46 8         34 push @renderer_paths, 'templates';
47              
48             my %config = (
49             INCLUDE_PATH => \@renderer_paths,
50             COMPILE_EXT => '.ttc',
51             UNICODE => 1,
52             ENCODING => 'utf-8',
53             CACHE_SIZE => 128,
54             RELATIVE => 1,
55 8 50       21 %{$args{template_options} || {}},
  8         92  
56             );
57              
58 8 50       38 if ( !exists( $config{COMPILE_DIR} ) ) {
59 0   0     0 $config{COMPILE_DIR} //= $dir || do {
      0        
60             my $tmpdir = File::Spec->catdir(File::Spec->tmpdir, "ttr$<");
61             mkdir $tmpdir unless -d $tmpdir;
62             $tmpdir;
63             };
64             }
65              
66             $config{LOAD_TEMPLATES} =
67             [Mojolicious::Plugin::TtRenderer::Provider->new(%config, renderer => $app->renderer)]
68 8 50       72 unless $config{LOAD_TEMPLATES};
69              
70 8 50       82 $self->tt(Template->new(\%config))
71             or Carp::croak "Could not initialize Template object: $Template::ERROR";
72              
73 8         196614 $self;
74             }
75              
76             sub _render {
77 36     36   131 my ($self, $renderer, $c, $output, $options) = @_;
78              
79             # Inline
80 36         97 my $inline = $options->{inline};
81              
82             # Template
83 36         129 my $t = $renderer->template_name($options);
84 36 100       634 $t = 'inline' if defined $inline;
85 36 50       113 return unless $t;
86              
87 36         331 my $helper = Mojolicious::Plugin::TtRenderer::Helper->new(ctx => $c);
88              
89             # fixes for t/lite_app_with_default_layouts.t
90 36 100       397 unless ($c->stash->{layout}) {
91 35   66     400 $c->stash->{content} ||= $c->stash->{'mojo.content'}->{content};
92             }
93              
94 36         709 my @params = ({%{$c->stash}, c => $c, h => $helper}, $output, {binmode => ':utf8'});
  36         111  
95 36         832 my $provider = $self->tt->{SERVICE}->{CONTEXT}->{LOAD_TEMPLATES}->[0];
96 36         439 $provider->options($options);
97              
98 36         70 my $ok = do {
99 36 100       119 if (defined $inline) {
100 1         5 $self->tt->process(\$inline, @params);
101             }
102             else {
103 35         245 my @ret = $provider->fetch($t);
104              
105 35 100       30772 if (not defined $ret[1]) {
    50          
106 27         159 $self->tt->process($ret[0], @params);
107             }
108             elsif (not defined $ret[0]) { # not found
109 0         0 return;
110             }
111             else { # error
112 8 100 66     157 return if $! == ENOENT && (not ref $ret[0]); # not found when not blessed exception
113 2         24 die $ret[0];
114             }
115             }
116             };
117              
118             # Error
119 28 100       14064 die $self->tt->error unless $ok;
120             }
121              
122             1; # End of Mojolicious::Plugin::TtRenderer::Engine
123              
124             package
125             Mojolicious::Plugin::TtRenderer::Helper;
126              
127 9     9   13532 use strict;
  9         26  
  9         310  
128 9     9   57 use warnings;
  9         54  
  9         392  
129              
130 9     9   76 use base 'Mojo::Base';
  9         23  
  9         3111  
131              
132             our $AUTOLOAD;
133              
134             __PACKAGE__->attr('ctx');
135              
136             sub AUTOLOAD {
137 8     8   2062 my $self = shift;
138              
139 8         23 my $method = $AUTOLOAD;
140              
141 8 50       42 return if $method =~ /^[A-Z]+?$/;
142 8 50       23 return if $method =~ /^_/;
143 8 50       27 return if $method =~ /(?:\:*?)DESTROY$/;
144              
145 8         37 $method = (split /::/, $method)[-1];
146              
147 8 100       36 die qq/Unknown helper: $method/ unless $self->ctx->app->renderer->helpers->{$method};
148              
149 7         133 $self->ctx->$method(@_);
150             }
151              
152             1;
153              
154             package
155             Mojolicious::Plugin::TtRenderer::Provider;
156              
157 9     9   424 use strict;
  9         21  
  9         259  
158 9     9   55 use warnings;
  9         19  
  9         330  
159              
160 9     9   74 use base 'Template::Provider';
  9         19  
  9         978  
161 9     9   73 use Scalar::Util 'weaken';
  9         18  
  9         4983  
162              
163             sub new {
164 8     8   74 my $class = shift;
165 8         45 my %params = @_;
166              
167 8         21 my $renderer = delete $params{renderer};
168              
169 8         120 my $self = $class->SUPER::new(%params);
170 8         7371 $self->renderer($renderer);
171 8         41 $self;
172             }
173              
174 42 100   42   284 sub renderer { @_ > 1 ? weaken($_[0]->{renderer} = $_[1]) : $_[0]->{renderer} }
175 36 50   36   174 sub options { @_ > 1 ? $_[0]->{options} = $_[1] : $_[0]->{options} }
176              
177             sub _template_modified {
178 104     104   284972 my($self, $template) = @_;
179 104 100 100     392 $self->SUPER::_template_modified($template) || $template =~ /^templates(?:\/|\\)/ || undef;
180             }
181              
182             sub _template_content {
183 41     41   1193 my $self = shift;
184 41         105 my ($path) = @_;
185              
186 41         136 my $options = delete $self->{options};
187              
188             # Convert backslashes to forward slashes to make inline templates work on Windows
189 41         129 $path =~ s/\\/\//g;
190 41         261 my ($t) = ($path =~ m{templates\/(.*)$});
191              
192 41 100       525 if (-r $path) {
193 7         103 return $self->SUPER::_template_content(@_);
194             }
195              
196 34         109 my $data;
197 34         78 my $error = '';
198              
199             # Try DATA section
200 34 100       107 if(defined $options) {
201 26         95 $data = $self->renderer->get_data_template($options);
202             } else {
203 8         20 foreach my $class (@{ $self->renderer->classes }) {
  8         41  
204 11         87 $data = Mojo::Loader::data_section($class, $t);
205 11 100       141 last if $data;
206             }
207             }
208              
209 34 100       936 unless($data) {
210 8         21 $data = '';
211 8         21 $error = "$path: not found";
212             }
213 34 50       194 wantarray ? ($data, $error, time) : $data; ## no critic (Freenode::Wantarray)
214             }
215              
216             1;
217              
218             __END__