File Coverage

blib/lib/Mojolicious/Plugin/RenderCGI.pm
Criterion Covered Total %
statement 53 58 91.3
branch 24 30 80.0
condition 12 22 54.5
subroutine 7 7 100.0
pod 1 3 33.3
total 97 120 80.8


line stmt bran cond sub pod time code
1             package Mojolicious::Plugin::RenderCGI;
2              
3 1     1   1321 use Mojo::Base 'Mojolicious::Plugin';
  1         2  
  1         10  
4 1     1   1244 use Mojolicious::Plugin::RenderCGI::Template;
  1         4  
  1         17  
5 1     1   43 use Mojo::Util qw(encode md5_sum);
  1         1  
  1         945  
6              
7             our $VERSION = '0.100';
8             my $pkg = __PACKAGE__;
9              
10             has qw(app);
11             has handler_name => 'cgi.pl';
12             has default => 0;
13             has cgi_import => sub { [qw(:html :form)] };
14             has exception => sub { {'handler'=>'ep', 'layout' => undef,} };
15             has cache => sub { {} };
16              
17             sub register {
18 2     2 1 7165 my ($plugin, $app, $conf) = @_;
19            
20 2         10 $plugin->app($app);
21            
22 2         31 map $plugin->$_($conf->{$_}), grep defined($conf->{$_}), qw(name default import exception);
23             #~ $app->renderer->default_handler($plugin->handler_name) не работает
24 2 50 50     30 $app->log->debug("Set default render handler ".$plugin->handler_name)
25             and $app->defaults('handler'=>$plugin->handler_name)
26             if $plugin->default;
27            
28             $app->renderer->add_handler(
29 14     14   148766 $plugin->handler_name => sub {$plugin->handler(@_)}
30 2         565 );
31             }
32              
33             sub handler {
34 14     14 0 44 my ($plugin, $r, $c, $output, $options) = @_;
35 14         55 my $app = $c->app;
36             #~ $app->log->debug($app->dumper($options));
37            
38             # относительный путь шаблона
39 14         80 my $content = $options->{inline};# встроенный шаблон
40 14 100       56 my $name = defined $content ? md5_sum encode('UTF-8', $content) : undef;
41 14 50 66     149 return unless defined($name //= $r->template_name($options));
42            
43             #~ my $url = Mojo::URL->new($name);
44             #~ ($name, my $param) = (url_unescape($url->path), $url->query->to_hash);
45             #~ utf8::decode($name);
46            
47 14         370 my ($template, $from) = ($plugin->cache->{$name}, 'cache');# подходящий шаблон из кэша
48            
49 14         145 my $stash = $c->stash($pkg);
50 14 100       253 $c->stash($pkg => {stack => []})
51             unless $stash;
52 14   66     266 $stash ||= $c->stash($pkg);
53 14         156 my $last_template = $stash->{stack}[-1];
54 14 50 66     76 if ($last_template && $last_template eq $name) {
55 0         0 $$output = $plugin->error("Stop looping template [$name]!", $c);
56 0         0 return;
57             }
58 14         23 push @{$stash->{stack}}, $name;
  14         48  
59            
60 14         34 $$output = '';
61            
62 14 100       42 unless ($template) {#не кэш
63 13 100       45 if (defined $content) {# инлайн
64 1         5 $from = 'inline';
65             } else {
66             # подходящий шаблон в секции DATA
67 12         64 ($content, $from) = ($r->get_data_template($options), 'DATA section');#,, $name
68            
69 12 100       459 unless (defined $content) {# file
70             # абсолютный путь шаблона
71 3 50       17 if (my $path = $r->template_path($options)) {
72 0         0 my $file = Mojo::Asset::File->new(path => $path);
73 0         0 ($content, $from) = ($file->slurp, 'file');
74            
75             } else {
76 3         440 $$output = $plugin->error(sprintf(qq{Template "%s" does not found}, $name), $c);
77 3         41 return;
78             }
79             }
80             }
81            
82 10 100 50     77 $app->log->debug(sprintf(qq{Empty or nothing template "%s"}, $name))
83             and return
84             unless $content =~ /\w/;
85            
86 7         35 utf8::decode($content);
87            
88 7         49 $template = Mojolicious::Plugin::RenderCGI::Template->new(_import=>$plugin->cgi_import, _plugin=>$plugin, );
89              
90 7         49 my $err = $template->_compile($content);
91            
92 7 100 50     49 $$output = $plugin->error(sprintf(qq{Compile time error for template "%s" from the %s: %s}, $name, $from, $err), $c)
93             and return
94             unless ref $err; # ref success
95            
96             }
97            
98 7         49 $app->log->debug(sprintf(qq{Rendering template "%s" from the %s}, $name, $from,));
99 7   66     370 $plugin->cache->{$name} ||= $template;
100            
101 7         94 my @out = eval { $template->_run($c)};
  7         40  
102 7 100 50     2424 $$output = $plugin->error(sprintf(qq{Runtime error for template "%s" from the %s:\n%s}, $name, $from, $@), $c)
103             and return
104             if $@;
105            
106 6         115 $$output = join "\n", grep defined, @out;
107            
108             }
109              
110             sub error {# харе
111 5     5 0 54 my ($plugin, $error, $c) = @_;
112 5 50 0     22 $c->stash(%{$plugin->exception})
  0         0  
113             and die $error
114             if ref($plugin->exception) eq 'HASH';
115            
116 5         69 $c->app->log->error($error);# лог после die!
117 5 100       196 return $error
118             if $plugin->exception eq 'template';
119            
120 1 50       10 return ""
121             if $plugin->exception =~ m'comment';
122             };
123              
124             1;
125              
126              
127             =pod
128              
129             =encoding utf8
130              
131             Доброго всем
132              
133             =head1 Mojolicious::Plugin::RenderCGI
134              
135             ¡ ¡ ¡ ALL GLORY TO GLORIA ! ! !
136              
137             =head1 VERSION
138              
139             0.100
140              
141             =head1 NAME
142              
143             Mojolicious::Plugin::RenderCGI - Rendering template with Perl code and CGI.pm funcs/subs for tags emits.
144              
145             =head1 SYNOPSIS
146              
147             $app->plugin('RenderCGI');
148              
149             =head1 Template
150              
151             Template is a Perl code that generate content as list of statements. Similar to C. Template file name like "templates/foo/bar.html.cgi.pl"
152              
153             # Predefined variables:
154             # $self is a Mojolicious::Plugin::RenderCGI::Template object
155             # $c is a current controller object
156             # $cgi is a CGI object
157            
158             $c->layout('default', handler=>'ep',);# set handler 'ep' for all templates/includes !!! even default handler cgi
159             my $foo = $c->stash('foo')
160             or die "Where is your FOO?";
161            
162             #=======================================
163             #======= content comma list! ===========
164             #=======================================
165            
166             h1({}, "Welcome"),# but this template handlered cgi!
167            
168             $c->include('foo', handler=>'cgi.pl'),# change handler against layout
169             $c->include('bar'); # handler still "ep" unless template "foo" (and its includes) didn`t changes it by $c->stash('handler'=>...)
170            
171             <
172            
173             END_HTML
174            
175             $self->app->log->info("Template has done")
176             && undef,
177              
178             There are NO Mojolicious helpers without OO-style prefixes: C<< $c-> >>.
179              
180             B Escapes untrusted data. No auto escapes!
181              
182             div({}, esc(...UNTRUSTED DATA...)),
183              
184             C is a shortcut for &CGI::escapeHTML.
185              
186             =head1 NOTE about autoloading subs and methods
187              
188             In template you can generate any tag:
189              
190             # ...
191             foo_tag({-class=>"class1",}, '...'),
192             # same
193             $self->foo_tag({-class=>"class1",}, '...'),
194              
195             =head1 OPTIONS
196              
197             =head2 handler_name ( string )
198              
199             # Mojolicious::Lite
200             plugin RenderCGI => {handler_name => 'pl'};
201              
202             Handler name, defaults to B.
203              
204             =head2 default (bool)
205              
206             When C then default handler. Defaults - 0 (no this default handler for app).
207              
208             default => 1,
209              
210             Is similar to C<< $app->defaults(handler=> ); >>
211              
212             =head2 cgi_import ( string (space delims) | arrayref )
213              
214             What subs do you want from CGI.pm import
215              
216             $app->plugin('RenderCGI', import=>':html ...');
217             # or
218             $app->plugin('RenderCGI', import=>[qw(:html ...)]);
219              
220             See at perldoc CGI.pm section "USING THE FUNCTION-ORIENTED INTERFACE".
221             Default is ':html :form' (string) same as [qw(:html :form)] (arrayref).
222              
223             cgi_import=>[], # none import subs CGI
224              
225             =head2 exception ( string | hashref )
226              
227             To show fatal errors (not found, compile and runtime errors) as content of there template you must set string B