Commit | Line | Data |
8077080c |
1 | package Catalyst::View::TT; |
2e322ce3 |
2 | use Moose; |
9e739e1e |
3 | use Data::Dump 'dump'; |
8077080c |
4 | use Template; |
5 | use Template::Timer; |
e8693f1b |
6 | use MRO::Compat; |
316f014a |
7 | use Scalar::Util qw/blessed/; |
2e322ce3 |
8 | use namespace::autoclean; |
9 | |
10 | extends 'Catalyst::View'; |
8077080c |
11 | |
bd45975e |
12 | our $VERSION = '0.33'; |
8077080c |
13 | |
2e322ce3 |
14 | has template => ( is => 'ro' ); |
15 | has include_path => ( is => 'rw' ); |
8077080c |
16 | |
2e322ce3 |
17 | __PACKAGE__->meta->add_method('paths' => __PACKAGE__->meta->find_method_by_name('include_path')); |
9d574573 |
18 | |
8077080c |
19 | =head1 NAME |
20 | |
21 | Catalyst::View::TT - Template View Class |
22 | |
23 | =head1 SYNOPSIS |
24 | |
bd4ee63a |
25 | # use the helper to create your View |
ad50568f |
26 | |
2e322ce3 |
27 | myapp_create.pl view HTML TT |
8077080c |
28 | |
6175bba7 |
29 | # configure in lib/MyApp.pm (Could be set from configfile instead) |
8cd017a8 |
30 | |
940a2e8a |
31 | __PACKAGE__->config( |
32 | name => 'MyApp', |
33 | root => MyApp->path_to('root'), |
34 | default_view => 'TT', |
2e322ce3 |
35 | 'View::HTML' => { |
8cd017a8 |
36 | # any TT configurations items go here |
37 | INCLUDE_PATH => [ |
f5b61ad7 |
38 | MyApp->path_to( 'root', 'src' ), |
39 | MyApp->path_to( 'root', 'lib' ), |
8cd017a8 |
40 | ], |
6175bba7 |
41 | TEMPLATE_EXTENSION => '.tt', |
42 | CATALYST_VAR => 'c', |
43 | TIMER => 0, |
44 | # Not set by default |
07571b2f |
45 | PRE_PROCESS => 'config/main', |
46 | WRAPPER => 'site/wrapper', |
3715305f |
47 | render_die => 1, # Default for new apps, see render method docs |
8cd017a8 |
48 | }, |
ae035767 |
49 | ); |
f5b61ad7 |
50 | |
6229ce0d |
51 | # render view from lib/MyApp.pm or lib/MyApp::Controller::SomeController.pm |
f5b61ad7 |
52 | |
8cd017a8 |
53 | sub message : Global { |
94b3529a |
54 | my ( $self, $c ) = @_; |
55 | $c->stash->{template} = 'message.tt2'; |
56 | $c->stash->{message} = 'Hello World!'; |
c18eae32 |
57 | $c->forward( $c->view('TT') ); |
8cd017a8 |
58 | } |
8077080c |
59 | |
8cd017a8 |
60 | # access variables from template |
61 | |
62 | The message is: [% message %]. |
f5b61ad7 |
63 | |
8cd017a8 |
64 | # example when CATALYST_VAR is set to 'Catalyst' |
f5b61ad7 |
65 | Context is [% Catalyst %] |
66 | The base is [% Catalyst.req.base %] |
67 | The name is [% Catalyst.config.name %] |
68 | |
8cd017a8 |
69 | # example when CATALYST_VAR isn't set |
70 | Context is [% c %] |
71 | The base is [% base %] |
72 | The name is [% name %] |
73 | |
bd4ee63a |
74 | =cut |
75 | |
76 | sub _coerce_paths { |
77 | my ( $paths, $dlim ) = shift; |
78 | return () if ( !$paths ); |
79 | return @{$paths} if ( ref $paths eq 'ARRAY' ); |
80 | |
81 | # tweak delim to ignore C:/ |
82 | unless ( defined $dlim ) { |
83 | $dlim = ( $^O eq 'MSWin32' ) ? ':(?!\\/)' : ':'; |
84 | } |
85 | return split( /$dlim/, $paths ); |
86 | } |
87 | |
2e322ce3 |
88 | #$class->merge_config_hashes( $class->config, $args ); |
89 | |
90 | around BUILDARGS => sub { |
91 | my ( $orig, $class, $c, $arguments ) = @_; |
92 | my $config = $class->merge_config_hashes( |
93 | { |
94 | EVAL_PERL => 0, |
95 | TEMPLATE_EXTENSION => '', |
96 | }, |
97 | $class->$orig($c, $arguments) |
98 | ); |
bd4ee63a |
99 | if ( ! (ref $config->{INCLUDE_PATH} eq 'ARRAY') ) { |
100 | my $delim = $config->{DELIMITER}; |
101 | my @include_path |
102 | = _coerce_paths( $config->{INCLUDE_PATH}, $delim ); |
103 | if ( !@include_path ) { |
104 | my $root = $c->config->{root}; |
105 | my $base = Path::Class::dir( $root, 'base' ); |
106 | @include_path = ( "$root", "$base" ); |
107 | } |
108 | $config->{INCLUDE_PATH} = \@include_path; |
109 | } |
110 | |
111 | # if we're debugging and/or the TIMER option is set, then we install |
112 | # Template::Timer as a custom CONTEXT object, but only if we haven't |
113 | # already got a custom CONTEXT defined |
114 | |
115 | if ( $config->{TIMER} ) { |
116 | if ( $config->{CONTEXT} ) { |
117 | $c->log->error( |
118 | 'Cannot use Template::Timer - a TT CONTEXT is already defined' |
119 | ); |
120 | } |
121 | else { |
122 | $config->{CONTEXT} = Template::Timer->new(%$config); |
123 | } |
124 | } |
125 | |
126 | if ( $c->debug && $config->{DUMP_CONFIG} ) { |
9e739e1e |
127 | $c->log->debug( "TT Config: ", dump($config) ); |
bd4ee63a |
128 | } |
6175bba7 |
129 | |
bd4ee63a |
130 | if ( $config->{PROVIDERS} ) { |
131 | my @providers = (); |
132 | if ( ref($config->{PROVIDERS}) eq 'ARRAY') { |
133 | foreach my $p (@{$config->{PROVIDERS}}) { |
134 | my $pname = $p->{name}; |
135 | my $prov = 'Template::Provider'; |
136 | if($pname eq '_file_') |
137 | { |
138 | $p->{args} = { %$config }; |
139 | } |
140 | else |
141 | { |
51199593 |
142 | if($pname =~ s/^\+//) { |
143 | $prov = $pname; |
144 | } |
145 | else |
146 | { |
147 | $prov .= "::$pname"; |
148 | } |
6175bba7 |
149 | # We copy the args people want from the config |
150 | # to the args |
151 | $p->{args} ||= {}; |
152 | if ($p->{copy_config}) { |
153 | map { $p->{args}->{$_} = $config->{$_} } |
154 | grep { exists $config->{$_} } |
155 | @{ $p->{copy_config} }; |
156 | } |
bd4ee63a |
157 | } |
fc0ffed0 |
158 | local $@; |
bd4ee63a |
159 | eval "require $prov"; |
160 | if(!$@) { |
161 | push @providers, "$prov"->new($p->{args}); |
162 | } |
163 | else |
164 | { |
165 | $c->log->warn("Can't load $prov, ($@)"); |
166 | } |
167 | } |
168 | } |
169 | delete $config->{PROVIDERS}; |
170 | if(@providers) { |
171 | $config->{LOAD_TEMPLATES} = \@providers; |
172 | } |
173 | } |
f5b61ad7 |
174 | |
2e322ce3 |
175 | $config->{template} = |
bd4ee63a |
176 | Template->new($config) || do { |
177 | my $error = Template->error(); |
178 | $c->log->error($error); |
179 | $c->error($error); |
180 | return undef; |
181 | }; |
182 | |
2e322ce3 |
183 | return $config; |
184 | }; |
185 | |
186 | sub BUILD { |
187 | my ($self, $config) = @_; |
188 | # Set base include paths. Local'd in render if needed |
189 | $self->include_path($config->{INCLUDE_PATH}); |
190 | |
191 | $self->config($config); |
bd4ee63a |
192 | |
2e322ce3 |
193 | # Creation of template outside of call to new so that we can pass [ $self ] |
194 | # as INCLUDE_PATH config item, which then gets ->paths() called to get list |
195 | # of include paths to search for templates. |
196 | |
197 | # Use a weakend copy of self so we dont have loops preventing GC from working |
198 | my $copy = $self; |
199 | Scalar::Util::weaken($copy); |
200 | $config->{INCLUDE_PATH} = [ sub { $copy->paths } ]; |
bd4ee63a |
201 | } |
202 | |
203 | sub process { |
204 | my ( $self, $c ) = @_; |
205 | |
206 | my $template = $c->stash->{template} |
207 | || $c->action . $self->config->{TEMPLATE_EXTENSION}; |
208 | |
209 | unless (defined $template) { |
210 | $c->log->debug('No template specified for rendering') if $c->debug; |
211 | return 0; |
212 | } |
213 | |
fc0ffed0 |
214 | local $@; |
cad820fe |
215 | my $output = eval { $self->render($c, $template) }; |
216 | if (my $err = $@) { |
316f014a |
217 | return $self->_rendering_error($c, $err); |
218 | } |
219 | if (blessed($output) && $output->isa('Template::Exception')) { |
220 | $self->_rendering_error($c, $output); |
bd4ee63a |
221 | } |
222 | |
223 | unless ( $c->response->content_type ) { |
224 | $c->response->content_type('text/html; charset=utf-8'); |
225 | } |
226 | |
227 | $c->response->body($output); |
228 | |
229 | return 1; |
230 | } |
231 | |
316f014a |
232 | sub _rendering_error { |
233 | my ($self, $c, $err) = @_; |
234 | my $error = qq/Couldn't render template "$err"/; |
235 | $c->log->error($error); |
236 | $c->error($error); |
237 | return 0; |
238 | } |
239 | |
bd4ee63a |
240 | sub render { |
241 | my ($self, $c, $template, $args) = @_; |
242 | |
cbb149dc |
243 | $c->log->debug(qq/Rendering template "$template"/) if $c && $c->debug; |
bd4ee63a |
244 | |
245 | my $output; |
f5b61ad7 |
246 | my $vars = { |
bd4ee63a |
247 | (ref $args eq 'HASH' ? %$args : %{ $c->stash() }), |
248 | $self->template_vars($c) |
249 | }; |
250 | |
f5b61ad7 |
251 | local $self->{include_path} = |
bd4ee63a |
252 | [ @{ $vars->{additional_template_paths} }, @{ $self->{include_path} } ] |
253 | if ref $vars->{additional_template_paths}; |
254 | |
596ff245 |
255 | unless ( $self->template->process( $template, $vars, \$output ) ) { |
256 | if (exists $self->{render_die}) { |
257 | die $self->template->error if $self->{render_die}; |
258 | return $self->template->error; |
259 | } |
316f014a |
260 | $c->log->debug('The Catalyst::View::TT render() method of will die on error in a future release. Unless you are calling the render() method manually, you probably want the new behaviour, so set render_die => 1 in config for ' . blessed($self) . '. If you are calling the render() method manually and you wish it to continue to return the exception rather than throwing it, add render_die => 0 to your config.') if $c->debug; |
596ff245 |
261 | return $self->template->error; |
262 | } |
cad820fe |
263 | return $output; |
bd4ee63a |
264 | } |
265 | |
266 | sub template_vars { |
267 | my ( $self, $c ) = @_; |
268 | |
cbb149dc |
269 | return () unless $c; |
bd4ee63a |
270 | my $cvar = $self->config->{CATALYST_VAR}; |
271 | |
272 | defined $cvar |
273 | ? ( $cvar => $c ) |
274 | : ( |
275 | c => $c, |
276 | base => $c->req->base, |
277 | name => $c->config->{name} |
278 | ) |
279 | } |
280 | |
281 | |
282 | 1; |
283 | |
284 | __END__ |
285 | |
8cd017a8 |
286 | =head1 DESCRIPTION |
287 | |
288 | This is the Catalyst view class for the L<Template Toolkit|Template>. |
289 | Your application should defined a view class which is a subclass of |
290 | this module. The easiest way to achieve this is using the |
291 | F<myapp_create.pl> script (where F<myapp> should be replaced with |
292 | whatever your application is called). This script is created as part |
293 | of the Catalyst setup. |
294 | |
295 | $ script/myapp_create.pl view TT TT |
296 | |
6229ce0d |
297 | This creates a MyApp::View::TT.pm module in the F<lib> directory (again, |
8cd017a8 |
298 | replacing C<MyApp> with the name of your application) which looks |
299 | something like this: |
300 | |
6229ce0d |
301 | package FooBar::View::TT; |
f5b61ad7 |
302 | |
8cd017a8 |
303 | use strict; |
c18eae32 |
304 | use warnings; |
f5b61ad7 |
305 | |
c18eae32 |
306 | use base 'Catalyst::View::TT'; |
8077080c |
307 | |
a1b7968f |
308 | __PACKAGE__->config(DEBUG => 'all'); |
8077080c |
309 | |
8cd017a8 |
310 | Now you can modify your action handlers in the main application and/or |
311 | controllers to forward to your view class. You might choose to do this |
312 | in the end() method, for example, to automatically forward all actions |
313 | to the TT view class. |
722fede4 |
314 | |
8cd017a8 |
315 | # In MyApp or MyApp::Controller::SomeController |
f5b61ad7 |
316 | |
8cd017a8 |
317 | sub end : Private { |
94b3529a |
318 | my( $self, $c ) = @_; |
c18eae32 |
319 | $c->forward( $c->view('TT') ); |
8cd017a8 |
320 | } |
8077080c |
321 | |
2844488f |
322 | But if you are using the standard auto-generated end action, you don't even need |
323 | to do this! |
324 | |
325 | # in MyApp::Controller::Root |
326 | sub end : ActionClass('RenderView') {} # no need to change this line |
327 | |
328 | # in MyApp.pm |
329 | __PACKAGE__->config( |
330 | ... |
331 | default_view => 'TT', |
332 | ); |
333 | |
334 | This will Just Work. And it has the advantages that: |
335 | |
336 | =over 4 |
337 | |
338 | =item * |
339 | |
340 | If you want to use a different view for a given request, just set |
341 | << $c->stash->{current_view} >>. (See L<Catalyst>'s C<< $c->view >> method |
342 | for details. |
343 | |
344 | =item * |
345 | |
346 | << $c->res->redirect >> is handled by default. If you just forward to |
347 | C<View::TT> in your C<end> routine, you could break this by sending additional |
348 | content. |
349 | |
350 | =back |
351 | |
352 | See L<Catalyst::Action::RenderView> for more details. |
353 | |
8cd017a8 |
354 | =head2 CONFIGURATION |
4687ac0d |
355 | |
8cd017a8 |
356 | There are a three different ways to configure your view class. The |
357 | first way is to call the C<config()> method in the view subclass. This |
358 | happens when the module is first loaded. |
8077080c |
359 | |
6229ce0d |
360 | package MyApp::View::TT; |
f5b61ad7 |
361 | |
8cd017a8 |
362 | use strict; |
363 | use base 'Catalyst::View::TT'; |
722fede4 |
364 | |
6229ce0d |
365 | MyApp::View::TT->config({ |
7d8aa5ec |
366 | INCLUDE_PATH => [ |
367 | MyApp->path_to( 'root', 'templates', 'lib' ), |
368 | MyApp->path_to( 'root', 'templates', 'src' ), |
369 | ], |
8cd017a8 |
370 | PRE_PROCESS => 'config/main', |
371 | WRAPPER => 'site/wrapper', |
372 | }); |
373 | |
374 | The second way is to define a C<new()> method in your view subclass. |
375 | This performs the configuration when the view object is created, |
376 | shortly after being loaded. Remember to delegate to the base class |
e8693f1b |
377 | C<new()> method (via C<$self-E<gt>next::method()> in the example below) after |
8cd017a8 |
378 | performing any configuration. |
379 | |
380 | sub new { |
381 | my $self = shift; |
382 | $self->config({ |
7d8aa5ec |
383 | INCLUDE_PATH => [ |
384 | MyApp->path_to( 'root', 'templates', 'lib' ), |
385 | MyApp->path_to( 'root', 'templates', 'src' ), |
386 | ], |
8cd017a8 |
387 | PRE_PROCESS => 'config/main', |
388 | WRAPPER => 'site/wrapper', |
389 | }); |
e8693f1b |
390 | return $self->next::method(@_); |
8cd017a8 |
391 | } |
f5b61ad7 |
392 | |
94b3529a |
393 | The final, and perhaps most direct way, is to define a class |
8cd017a8 |
394 | item in your main application configuration, again by calling the |
ad50568f |
395 | ubiquitous C<config()> method. The items in the class hash are |
8cd017a8 |
396 | added to those already defined by the above two methods. This happens |
397 | in the base class new() method (which is one reason why you must |
f5b61ad7 |
398 | remember to call it via C<MRO::Compat> if you redefine the C<new()> |
e8693f1b |
399 | method in a subclass). |
8cd017a8 |
400 | |
401 | package MyApp; |
f5b61ad7 |
402 | |
8cd017a8 |
403 | use strict; |
404 | use Catalyst; |
f5b61ad7 |
405 | |
8cd017a8 |
406 | MyApp->config({ |
407 | name => 'MyApp', |
7d8aa5ec |
408 | root => MyApp->path_to('root'), |
6229ce0d |
409 | 'View::TT' => { |
7d8aa5ec |
410 | INCLUDE_PATH => [ |
411 | MyApp->path_to( 'root', 'templates', 'lib' ), |
412 | MyApp->path_to( 'root', 'templates', 'src' ), |
413 | ], |
8cd017a8 |
414 | PRE_PROCESS => 'config/main', |
415 | WRAPPER => 'site/wrapper', |
416 | }, |
417 | }); |
418 | |
419 | Note that any configuration items defined by one of the earlier |
420 | methods will be overwritten by items of the same name provided by the |
f5b61ad7 |
421 | latter methods. |
8cd017a8 |
422 | |
e2bbd784 |
423 | =head2 DYNAMIC INCLUDE_PATH |
424 | |
f7dfca06 |
425 | Sometimes it is desirable to modify INCLUDE_PATH for your templates at run time. |
f5b61ad7 |
426 | |
f7dfca06 |
427 | Additional paths can be added to the start of INCLUDE_PATH via the stash as |
428 | follows: |
429 | |
430 | $c->stash->{additional_template_paths} = |
431 | [$c->config->{root} . '/test_include_path']; |
432 | |
433 | If you need to add paths to the end of INCLUDE_PATH, there is also an |
434 | include_path() accessor available: |
435 | |
436 | push( @{ $c->view('TT')->include_path }, qw/path/ ); |
437 | |
438 | Note that if you use include_path() to add extra paths to INCLUDE_PATH, you |
439 | MUST check for duplicate paths. Without such checking, the above code will add |
440 | "path" to INCLUDE_PATH at every request, causing a memory leak. |
441 | |
442 | A safer approach is to use include_path() to overwrite the array of paths |
443 | rather than adding to it. This eliminates both the need to perform duplicate |
444 | checking and the chance of a memory leak: |
e2bbd784 |
445 | |
f7dfca06 |
446 | @{ $c->view('TT')->include_path } = qw/path another_path/; |
e2bbd784 |
447 | |
f5b61ad7 |
448 | If you are calling C<render> directly then you can specify dynamic paths by |
9d574573 |
449 | having a C<additional_template_paths> key with a value of additonal directories |
1bc9fc55 |
450 | to search. See L<CAPTURING TEMPLATE OUTPUT> for an example showing this. |
451 | |
8cd017a8 |
452 | =head2 RENDERING VIEWS |
453 | |
454 | The view plugin renders the template specified in the C<template> |
f5b61ad7 |
455 | item in the stash. |
8cd017a8 |
456 | |
457 | sub message : Global { |
94b3529a |
458 | my ( $self, $c ) = @_; |
459 | $c->stash->{template} = 'message.tt2'; |
6229ce0d |
460 | $c->forward( $c->view('TT') ); |
8cd017a8 |
461 | } |
722fede4 |
462 | |
c969f23a |
463 | If a stash item isn't defined, then it instead uses the |
464 | stringification of the action dispatched to (as defined by $c->action) |
465 | in the above example, this would be C<message>, but because the default |
466 | is to append '.tt', it would load C<root/message.tt>. |
8cd017a8 |
467 | |
468 | The items defined in the stash are passed to the Template Toolkit for |
469 | use as template variables. |
470 | |
8cd017a8 |
471 | sub default : Private { |
94b3529a |
472 | my ( $self, $c ) = @_; |
473 | $c->stash->{template} = 'message.tt2'; |
474 | $c->stash->{message} = 'Hello World!'; |
6229ce0d |
475 | $c->forward( $c->view('TT') ); |
8cd017a8 |
476 | } |
7b592fc7 |
477 | |
8cd017a8 |
478 | A number of other template variables are also added: |
8077080c |
479 | |
8cd017a8 |
480 | c A reference to the context object, $c |
481 | base The URL base, from $c->req->base() |
482 | name The application name, from $c->config->{ name } |
483 | |
484 | These can be accessed from the template in the usual way: |
485 | |
486 | <message.tt2>: |
487 | |
488 | The message is: [% message %] |
489 | The base is [% base %] |
490 | The name is [% name %] |
491 | |
8cd017a8 |
492 | |
1bc9fc55 |
493 | The output generated by the template is stored in C<< $c->response->body >>. |
494 | |
495 | =head2 CAPTURING TEMPLATE OUTPUT |
496 | |
497 | If you wish to use the output of a template for some other purpose than |
498 | displaying in the response, e.g. for sending an email, this is possible using |
499 | L<Catalyst::Plugin::Email> and the L<render> method: |
500 | |
501 | sub send_email : Local { |
502 | my ($self, $c) = @_; |
f5b61ad7 |
503 | |
1bc9fc55 |
504 | $c->email( |
505 | header => [ |
506 | To => 'me@localhost', |
507 | Subject => 'A TT Email', |
508 | ], |
509 | body => $c->view('TT')->render($c, 'email.tt', { |
9d574573 |
510 | additional_template_paths => [ $c->config->{root} . '/email_templates'], |
1bc9fc55 |
511 | email_tmpl_param1 => 'foo' |
512 | } |
513 | ), |
514 | ); |
515 | # Redirect or display a message |
516 | } |
8cd017a8 |
517 | |
518 | =head2 TEMPLATE PROFILING |
519 | |
1bc9fc55 |
520 | See L<C<TIMER>> property of the L<config> method. |
521 | |
caa61517 |
522 | =head2 METHODS |
8077080c |
523 | |
b63ddd04 |
524 | =head2 new |
2774dc77 |
525 | |
f5b61ad7 |
526 | The constructor for the TT view. Sets up the template provider, |
2774dc77 |
527 | and reads the application config. |
528 | |
81b7f2a2 |
529 | =head2 process($c) |
8077080c |
530 | |
1bc9fc55 |
531 | Renders the template specified in C<< $c->stash->{template} >> or |
ad50568f |
532 | C<< $c->action >> (the private name of the matched action). Calls L<render> to |
1bc9fc55 |
533 | perform actual rendering. Output is stored in C<< $c->response->body >>. |
8077080c |
534 | |
81b7f2a2 |
535 | It is possible to forward to the process method of a TT view from inside |
536 | Catalyst like this: |
537 | |
538 | $c->forward('View::TT'); |
539 | |
540 | N.B. This is usually done automatically by L<Catalyst::Action::RenderView>. |
f2ee4d6c |
541 | |
b63ddd04 |
542 | =head2 render($c, $template, \%args) |
1bc9fc55 |
543 | |
cad820fe |
544 | Renders the given template and returns output. Throws a L<Template::Exception> |
f5b61ad7 |
545 | object upon error. |
1bc9fc55 |
546 | |
f5b61ad7 |
547 | The template variables are set to C<%$args> if $args is a hashref, or |
548 | $C<< $c->stash >> otherwise. In either case the variables are augmented with |
1bc9fc55 |
549 | C<base> set to C< << $c->req->base >>, C<c> to C<$c> and C<name> to |
550 | C<< $c->config->{name} >>. Alternately, the C<CATALYST_VAR> configuration item |
551 | can be defined to specify the name of a template variable through which the |
552 | context reference (C<$c>) can be accessed. In this case, the C<c>, C<base> and |
553 | C<name> variables are omitted. |
554 | |
f5b61ad7 |
555 | C<$template> can be anything that Template::process understands how to |
1bc9fc55 |
556 | process, including the name of a template file or a reference to a test string. |
557 | See L<Template::process|Template/process> for a full list of supported formats. |
558 | |
f59953e1 |
559 | To use the render method outside of your Catalyst app, just pass a undef context. |
cbb149dc |
560 | This can be useful for tests, for instance. |
561 | |
81b7f2a2 |
562 | It is possible to forward to the render method of a TT view from inside Catalyst |
563 | to render page fragments like this: |
564 | |
565 | my $fragment = $c->forward("View::TT", "render", $template_name, $c->stash->{fragment_data}); |
f2ee4d6c |
566 | |
3715305f |
567 | =head3 Backwards compatibility note |
568 | |
569 | The render method used to just return the Template::Exception object, rather |
570 | than just throwing it. This is now deprecated and instead the render method |
571 | will throw an exception for new applications. |
572 | |
573 | This behaviour can be activated (and is activated in the default skeleton |
574 | configuration) by using C<< render_die => 1 >>. If you rely on the legacy |
575 | behaviour then a warning will be issued. |
576 | |
577 | To silence this warning, set C<< render_die => 0 >>, but it is recommended |
578 | you adjust your code so that it works with C<< render_die => 1 >>. |
579 | |
580 | In a future release, C<< render_die => 1 >> will become the default if |
581 | unspecified. |
582 | |
b63ddd04 |
583 | =head2 template_vars |
850ee226 |
584 | |
1bc9fc55 |
585 | Returns a list of keys/values to be used as the catalyst variables in the |
850ee226 |
586 | template. |
587 | |
b63ddd04 |
588 | =head2 config |
8077080c |
589 | |
8cd017a8 |
590 | This method allows your view subclass to pass additional settings to |
4729c102 |
591 | the TT configuration hash, or to set the options as below: |
592 | |
b63ddd04 |
593 | =head2 paths |
594 | |
595 | The list of paths TT will look for templates in. |
4729c102 |
596 | |
f5b61ad7 |
597 | =head2 C<CATALYST_VAR> |
4729c102 |
598 | |
599 | Allows you to change the name of the Catalyst context object. If set, it will also |
600 | remove the base and name aliases, so you will have access them through <context>. |
601 | |
602 | For example: |
603 | |
604 | MyApp->config({ |
605 | name => 'MyApp', |
7d8aa5ec |
606 | root => MyApp->path_to('root'), |
6229ce0d |
607 | 'View::TT' => { |
4729c102 |
608 | CATALYST_VAR => 'Catalyst', |
609 | }, |
610 | }); |
611 | |
612 | F<message.tt2>: |
613 | |
614 | The base is [% Catalyst.req.base %] |
615 | The name is [% Catalyst.config.name %] |
616 | |
b63ddd04 |
617 | =head2 C<TIMER> |
4729c102 |
618 | |
619 | If you have configured Catalyst for debug output, and turned on the TIMER setting, |
620 | C<Catalyst::View::TT> will enable profiling of template processing |
621 | (using L<Template::Timer>). This will embed HTML comments in the |
622 | output from your templates, such as: |
623 | |
624 | <!-- TIMER START: process mainmenu/mainmenu.ttml --> |
625 | <!-- TIMER START: include mainmenu/cssindex.tt --> |
626 | <!-- TIMER START: process mainmenu/cssindex.tt --> |
627 | <!-- TIMER END: process mainmenu/cssindex.tt (0.017279 seconds) --> |
628 | <!-- TIMER END: include mainmenu/cssindex.tt (0.017401 seconds) --> |
629 | |
630 | .... |
631 | |
632 | <!-- TIMER END: process mainmenu/footer.tt (0.003016 seconds) --> |
633 | |
634 | |
b63ddd04 |
635 | =head2 C<TEMPLATE_EXTENSION> |
4729c102 |
636 | |
747f2b6d |
637 | a sufix to add when looking for templates bases on the C<match> method in L<Catalyst::Request>. |
4729c102 |
638 | |
639 | For example: |
640 | |
6229ce0d |
641 | package MyApp::Controller::Test; |
f5b61ad7 |
642 | sub test : Local { .. } |
4729c102 |
643 | |
644 | Would by default look for a template in <root>/test/test. If you set TEMPLATE_EXTENSION to '.tt', it will look for |
645 | <root>/test/test.tt. |
646 | |
51199593 |
647 | =head2 C<PROVIDERS> |
648 | |
649 | Allows you to specify the template providers that TT will use. |
650 | |
651 | MyApp->config({ |
652 | name => 'MyApp', |
653 | root => MyApp->path_to('root'), |
6229ce0d |
654 | 'View::TT' => { |
51199593 |
655 | PROVIDERS => [ |
656 | { |
657 | name => 'DBI', |
658 | args => { |
659 | DBI_DSN => 'dbi:DB2:books', |
660 | DBI_USER=> 'foo' |
661 | } |
662 | }, { |
663 | name => '_file_', |
664 | args => {} |
665 | } |
666 | ] |
667 | }, |
668 | }); |
669 | |
670 | The 'name' key should correspond to the class name of the provider you |
671 | want to use. The _file_ name is a special case that represents the default |
672 | TT file-based provider. By default the name is will be prefixed with |
673 | 'Template::Provider::'. You can fully qualify the name by using a unary |
674 | plus: |
675 | |
676 | name => '+MyApp::Provider::Foo' |
677 | |
6175bba7 |
678 | You can also specify the 'copy_config' key as an arrayref, to copy those keys |
679 | from the general config, into the config for the provider: |
f5b61ad7 |
680 | |
6175bba7 |
681 | DEFAULT_ENCODING => 'utf-8', |
682 | PROVIDERS => [ |
683 | { |
684 | name => 'Encoding', |
685 | copy_config => [qw(DEFAULT_ENCODING INCLUDE_PATH)] |
686 | } |
687 | ] |
f5b61ad7 |
688 | |
6175bba7 |
689 | This can prove useful when you want to use the additional_template_paths hack |
690 | in your own provider, or if you need to use Template::Provider::Encoding |
691 | |
8cd017a8 |
692 | =head2 HELPERS |
693 | |
694 | The L<Catalyst::Helper::View::TT> and |
695 | L<Catalyst::Helper::View::TTSite> helper modules are provided to create |
696 | your view module. There are invoked by the F<myapp_create.pl> script: |
697 | |
698 | $ script/myapp_create.pl view TT TT |
699 | |
700 | $ script/myapp_create.pl view TT TTSite |
701 | |
702 | The L<Catalyst::Helper::View::TT> module creates a basic TT view |
703 | module. The L<Catalyst::Helper::View::TTSite> module goes a little |
704 | further. It also creates a default set of templates to get you |
705 | started. It also configures the view module to locate the templates |
706 | automatically. |
707 | |
02c64502 |
708 | =head1 NOTES |
709 | |
710 | If you are using the L<CGI> module inside your templates, you will |
711 | experience that the Catalyst server appears to hang while rendering |
712 | the web page. This is due to the debug mode of L<CGI> (which is |
713 | waiting for input in the terminal window). Turning off the |
714 | debug mode using the "-no_debug" option solves the |
715 | problem, eg.: |
716 | |
717 | [% USE CGI('-no_debug') %] |
718 | |
8077080c |
719 | =head1 SEE ALSO |
720 | |
8cd017a8 |
721 | L<Catalyst>, L<Catalyst::Helper::View::TT>, |
722 | L<Catalyst::Helper::View::TTSite>, L<Template::Manual> |
8077080c |
723 | |
c0eb0527 |
724 | =head1 AUTHORS |
8077080c |
725 | |
726 | Sebastian Riedel, C<sri@cpan.org> |
c0eb0527 |
727 | |
d938377b |
728 | Marcus Ramberg, C<mramberg@cpan.org> |
c0eb0527 |
729 | |
722fede4 |
730 | Jesse Sheidlower, C<jester@panix.com> |
c0eb0527 |
731 | |
8cd017a8 |
732 | Andy Wardley, C<abw@cpan.org> |
8077080c |
733 | |
734 | =head1 COPYRIGHT |
735 | |
f5b61ad7 |
736 | This program is free software. You can redistribute it and/or modify it |
2774dc77 |
737 | under the same terms as Perl itself. |
8077080c |
738 | |
739 | =cut |