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   537657 use warnings;
  9         26  
  9         296  
4 9     9   51 use strict;
  9         19  
  9         159  
5 9     9   175 use 5.016;
  9         41  
6 9     9   46 use base 'Mojo::Base';
  9         28  
  9         936  
7 9     9   60 use Carp ();
  9         25  
  9         184  
8 9     9   47 use File::Spec ();
  9         20  
  9         188  
9 9     9   456 use Mojo::ByteStream 'b';
  9         3713  
  9         542  
10 9     9   4867 use Template ();
  9         171843  
  9         294  
11 9     9   128 use Cwd qw/abs_path/;
  9         22  
  9         481  
12 9     9   57 use Scalar::Util 'weaken';
  9         20  
  9         376  
13 9     9   556 use POSIX ':errno_h';
  9         5562  
  9         74  
14              
15             # ABSTRACT: Template Toolkit renderer for Mojolicious
16             our $VERSION = '1.61'; # VERSION
17              
18             __PACKAGE__->attr('tt');
19              
20             sub build {
21 8     8 1 732 my $self = shift->SUPER::new(@_);
22 8         131 weaken($self->{app});
23 8         29 $self->_init(@_);
24 36     36   576846 sub { $self->_render(@_) }
25 8         65 }
26              
27             sub _init {
28 8     8   17 my $self = shift;
29 8         28 my %args = @_;
30              
31             #$Template::Parser::DEBUG = 1;
32              
33 8         16 my $dir;
34 8   66     67 my $app = delete $args{mojo} || delete $args{app};
35 8 100       34 if($dir=$args{cache_dir}) {
36              
37 1 50 33     7 if($app && substr($dir,0,1) ne '/') {
38 1         9 $dir=$app->home->rel_file($dir);
39             }
40             }
41              
42             # TODO
43             # take and process options :-)
44              
45 8 50       181 my @renderer_paths = $app ? map { abs_path($_) } grep { -d $_ } @{ $app->renderer->paths } : ();
  8         445  
  9         334  
  8         60  
46 8         33 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       23 %{$args{template_options} || {}},
  8         84  
56             );
57              
58 8 50       35 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       70 unless $config{LOAD_TEMPLATES};
69              
70 8 50       78 $self->tt(Template->new(\%config))
71             or Carp::croak "Could not initialize Template object: $Template::ERROR";
72              
73 8         187046 $self;
74             }
75              
76             sub _render {
77 36     36   123 my ($self, $renderer, $c, $output, $options) = @_;
78              
79             # Inline
80 36         85 my $inline = $options->{inline};
81              
82             # Template
83 36         122 my $t = $renderer->template_name($options);
84 36 100       607 $t = 'inline' if defined $inline;
85 36 50       108 return unless $t;
86              
87 36         296 my $helper = Mojolicious::Plugin::TtRenderer::Helper->new(ctx => $c);
88              
89             # fixes for t/lite_app_with_default_layouts.t
90 36 100       385 unless ($c->stash->{layout}) {
91 35   66     362 $c->stash->{content} ||= $c->stash->{'mojo.content'}->{content};
92             }
93              
94 36         632 my @params = ({%{$c->stash}, c => $c, h => $helper}, $output, {binmode => ':utf8'});
  36         116  
95 36         744 my $provider = $self->tt->{SERVICE}->{CONTEXT}->{LOAD_TEMPLATES}->[0];
96 36         404 $provider->options($options);
97              
98 36         66 my $ok = do {
99 36 100       99 if (defined $inline) {
100 1         5 $self->tt->process(\$inline, @params);
101             }
102             else {
103 35         221 my @ret = $provider->fetch($t);
104              
105 35 100       32703 if (not defined $ret[1]) {
    50          
106 27         139 $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     176 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       12715 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   12827 use strict;
  9         21  
  9         270  
128 9     9   96 use warnings;
  9         51  
  9         354  
129              
130 9     9   67 use base 'Mojo::Base';
  9         17  
  9         2863  
131              
132             our $AUTOLOAD;
133              
134             __PACKAGE__->attr('ctx');
135              
136             sub AUTOLOAD {
137 8     8   2027 my $self = shift;
138              
139 8         18 my $method = $AUTOLOAD;
140              
141 8 50       38 return if $method =~ /^[A-Z]+?$/;
142 8 50       25 return if $method =~ /^_/;
143 8 50       30 return if $method =~ /(?:\:*?)DESTROY$/;
144              
145 8         34 $method = (split /::/, $method)[-1];
146              
147 8 100       35 die qq/Unknown helper: $method/ unless $self->ctx->app->renderer->helpers->{$method};
148              
149 7         127 $self->ctx->$method(@_);
150             }
151              
152             1;
153              
154             package
155             Mojolicious::Plugin::TtRenderer::Provider;
156              
157 9     9   73 use strict;
  9         34  
  9         254  
158 9     9   55 use warnings;
  9         34  
  9         312  
159              
160 9     9   51 use base 'Template::Provider';
  9         21  
  9         918  
161 9     9   66 use Scalar::Util 'weaken';
  9         19  
  9         4558  
162              
163             sub new {
164 8     8   68 my $class = shift;
165 8         43 my %params = @_;
166              
167 8         22 my $renderer = delete $params{renderer};
168              
169 8         111 my $self = $class->SUPER::new(%params);
170 8         6823 $self->renderer($renderer);
171 8         39 $self;
172             }
173              
174 42 100   42   265 sub renderer { @_ > 1 ? weaken($_[0]->{renderer} = $_[1]) : $_[0]->{renderer} }
175 36 50   36   158 sub options { @_ > 1 ? $_[0]->{options} = $_[1] : $_[0]->{options} }
176              
177             sub _template_modified {
178 104     104   272992 my($self, $template) = @_;
179 104 100 100     416 $self->SUPER::_template_modified($template) || $template =~ /^templates(?:\/|\\)/ || undef;
180             }
181              
182             sub _template_content {
183 41     41   1174 my $self = shift;
184 41         112 my ($path) = @_;
185              
186 41         124 my $options = delete $self->{options};
187              
188             # Convert backslashes to forward slashes to make inline templates work on Windows
189 41         133 $path =~ s/\\/\//g;
190 41         256 my ($t) = ($path =~ m{templates\/(.*)$});
191              
192 41 100       500 if (-r $path) {
193 7         84 return $self->SUPER::_template_content(@_);
194             }
195              
196 34         92 my $data;
197 34         76 my $error = '';
198              
199             # Try DATA section
200 34 100       122 if(defined $options) {
201 26         103 $data = $self->renderer->get_data_template($options);
202             } else {
203 8         18 foreach my $class (@{ $self->renderer->classes }) {
  8         33  
204 11         81 $data = Mojo::Loader::data_section($class, $t);
205 11 100       137 last if $data;
206             }
207             }
208              
209 34 100       908 unless($data) {
210 8         20 $data = '';
211 8         24 $error = "$path: not found";
212             }
213 34 50       172 wantarray ? ($data, $error, time) : $data; ## no critic (Freenode::Wantarray)
214             }
215              
216             1;
217              
218             __END__