released
[catagits/Catalyst-View-TT.git] / lib / Catalyst / View / TT.pm
CommitLineData
8077080c 1package Catalyst::View::TT;
2
3use strict;
caa61517 4use base qw/Catalyst::Base/;
8077080c 5use Template;
6use Template::Timer;
7use NEXT;
8
19ee577a 9our $VERSION = '0.14';
8077080c 10
11__PACKAGE__->mk_accessors('template');
8077080c 12
13=head1 NAME
14
15Catalyst::View::TT - Template View Class
16
17=head1 SYNOPSIS
18
8cd017a8 19# use the helper to create View
722fede4 20 myapp_create.pl view TT TT
8077080c 21
8cd017a8 22# configure in lib/MyApp.pm
23
24 our $ROOT = '/home/dent/catalyst/MyApp';
25
26 MyApp->config({
27 name => 'MyApp',
28 root => $ROOT,
7d607671 29 'V::TT' => {
8cd017a8 30 # any TT configurations items go here
31 INCLUDE_PATH => [
32 "$ROOT/templates/src",
33 "$ROOT/templates/lib"
34 ],
35 PRE_PROCESS => 'config/main',
36 WRAPPER => 'site/wrapper',
37
38 # two optional config items
39 CATALYST_VAR => 'Catalyst',
40 TIMER => 1,
41 },
42 });
43
44# render view from lib/MyApp.pm or lib/MyApp::C::SomeController.pm
45
46 sub message : Global {
94b3529a 47 my ( $self, $c ) = @_;
48 $c->stash->{template} = 'message.tt2';
49 $c->stash->{message} = 'Hello World!';
8cd017a8 50 $c->forward('MyApp::V::TT');
51 }
8077080c 52
8cd017a8 53# access variables from template
54
55 The message is: [% message %].
56
57 # example when CATALYST_VAR is set to 'Catalyst'
58 Context is [% Catalyst %]
59 The base is [% Catalyst.req.base %]
60 The name is [% Catalyst.config.name %]
61
62 # example when CATALYST_VAR isn't set
63 Context is [% c %]
64 The base is [% base %]
65 The name is [% name %]
66
67=head1 DESCRIPTION
68
69This is the Catalyst view class for the L<Template Toolkit|Template>.
70Your application should defined a view class which is a subclass of
71this module. The easiest way to achieve this is using the
72F<myapp_create.pl> script (where F<myapp> should be replaced with
73whatever your application is called). This script is created as part
74of the Catalyst setup.
75
76 $ script/myapp_create.pl view TT TT
77
78This creates a MyApp::V::TT.pm module in the F<lib> directory (again,
79replacing C<MyApp> with the name of your application) which looks
80something like this:
81
82 package FooBar::V::TT;
83
84 use strict;
85 use base 'Catalyst::View::TT';
8077080c 86
87 __PACKAGE__->config->{DEBUG} = 'all';
88
8cd017a8 89Now you can modify your action handlers in the main application and/or
90controllers to forward to your view class. You might choose to do this
91in the end() method, for example, to automatically forward all actions
92to the TT view class.
722fede4 93
8cd017a8 94 # In MyApp or MyApp::Controller::SomeController
8077080c 95
8cd017a8 96 sub end : Private {
94b3529a 97 my( $self, $c ) = @_;
8cd017a8 98 $c->forward('MyApp::V::TT');
99 }
8077080c 100
8cd017a8 101=head2 CONFIGURATION
4687ac0d 102
8cd017a8 103There are a three different ways to configure your view class. The
104first way is to call the C<config()> method in the view subclass. This
105happens when the module is first loaded.
8077080c 106
8cd017a8 107 package MyApp::V::TT;
108
109 use strict;
110 use base 'Catalyst::View::TT';
722fede4 111
8cd017a8 112 our $ROOT = '/home/dent/catalyst/MyApp';
113
114 MyApp::V::TT->config({
115 INCLUDE_PATH => ["$ROOT/templates/src", "$ROOT/templates/lib"],
116 PRE_PROCESS => 'config/main',
117 WRAPPER => 'site/wrapper',
118 });
119
120The second way is to define a C<new()> method in your view subclass.
121This performs the configuration when the view object is created,
122shortly after being loaded. Remember to delegate to the base class
123C<new()> method (via C<$self-E<gt>NEXT::new()> in the example below) after
124performing any configuration.
125
126 sub new {
127 my $self = shift;
128 $self->config({
129 INCLUDE_PATH => ["$ROOT/templates/src", "$ROOT/templates/lib"],
130 PRE_PROCESS => 'config/main',
131 WRAPPER => 'site/wrapper',
132 });
133 return $self->NEXT::new(@_);
134 }
135
94b3529a 136The final, and perhaps most direct way, is to define a class
8cd017a8 137item in your main application configuration, again by calling the
94b3529a 138uniquitous C<config()> method. The items in the class hash are
8cd017a8 139added to those already defined by the above two methods. This happens
140in the base class new() method (which is one reason why you must
141remember to call it via C<NEXT> if you redefine the C<new()> method in a
142subclass).
143
144 package MyApp;
145
146 use strict;
147 use Catalyst;
148
149 our $ROOT = '/home/dent/catalyst/MyApp';
150
151 MyApp->config({
152 name => 'MyApp',
153 root => $ROOT,
7d607671 154 'V::TT' => {
8cd017a8 155 INCLUDE_PATH => ["$ROOT/templates/src", "$ROOT/templates/lib"],
156 PRE_PROCESS => 'config/main',
157 WRAPPER => 'site/wrapper',
158 },
159 });
160
161Note that any configuration items defined by one of the earlier
162methods will be overwritten by items of the same name provided by the
163latter methods.
164
165=head2 RENDERING VIEWS
166
167The view plugin renders the template specified in the C<template>
168item in the stash.
169
170 sub message : Global {
94b3529a 171 my ( $self, $c ) = @_;
172 $c->stash->{template} = 'message.tt2';
8cd017a8 173 $c->forward('MyApp::V::TT');
174 }
722fede4 175
94b3529a 176If a class item isn't defined, then it instead uses the
8cd017a8 177current match, as returned by C<$c-E<gt>match>. In the above
178example, this would be C<message>.
179
180The items defined in the stash are passed to the Template Toolkit for
181use as template variables.
182
183sub message : Global {
184 sub default : Private {
94b3529a 185 my ( $self, $c ) = @_;
186 $c->stash->{template} = 'message.tt2';
187 $c->stash->{message} = 'Hello World!';
8cd017a8 188 $c->forward('MyApp::V::TT');
189 }
7b592fc7 190
8cd017a8 191A number of other template variables are also added:
8077080c 192
8cd017a8 193 c A reference to the context object, $c
194 base The URL base, from $c->req->base()
195 name The application name, from $c->config->{ name }
196
197These can be accessed from the template in the usual way:
198
199<message.tt2>:
200
201 The message is: [% message %]
202 The base is [% base %]
203 The name is [% name %]
204
205If you prefer, you can set the C<CATALYST_VAR> configuration item to
206define the name of a template variable through which the context can
207be referenced.
208
209 MyApp->config({
210 name => 'MyApp',
211 root => $ROOT,
7d607671 212 'V::TT' => {
8cd017a8 213 CATALYST_VAR => 'Catalyst',
214 },
215 });
216
217F<message.tt2>:
218
219 The base is [% Catalyst.req.base %]
220 The name is [% Catalyst.config.name %]
221
222The output generated by the template is stored in
223C<$c-E<gt>response-E<gt>output>.
224
225=head2 TEMPLATE PROFILING
226
227If you have configured Catalyst for debug output,
228C<Catalyst::View::TT> will enable profiling of template processing
229(using L<Template::Timer>). This will embed HTML comments in the
230output from your templates, such as:
4687ac0d 231
232 <!-- TIMER START: process mainmenu/mainmenu.ttml -->
233 <!-- TIMER START: include mainmenu/cssindex.tt -->
234 <!-- TIMER START: process mainmenu/cssindex.tt -->
235 <!-- TIMER END: process mainmenu/cssindex.tt (0.017279 seconds) -->
236 <!-- TIMER END: include mainmenu/cssindex.tt (0.017401 seconds) -->
237
238 ....
239
240 <!-- TIMER END: process mainmenu/footer.tt (0.003016 seconds) -->
241
8cd017a8 242You can suppress template profiling by setting the C<TIMER> configuration
243item to a false value.
4687ac0d 244
8cd017a8 245 MyApp->config({
7d607671 246 'V::TT' => {
8cd017a8 247 TIMER => 0,
248 },
249 });
4687ac0d 250
caa61517 251=head2 METHODS
8077080c 252
2774dc77 253=over 4
254
255=item new
256
257The constructor for the TT view. Sets up the template provider,
258and reads the application config.
259
8077080c 260=cut
261
262sub new {
9300af5b 263 my ( $class, $c, $arguments ) = @_;
264
265 my $root = $c->config->{root};
266
94b3529a 267 my $config = {
caa61517 268 EVAL_PERL => 0,
269 INCLUDE_PATH => [ $root, "$root/base" ],
9300af5b 270 %{ $class->config },
8cd017a8 271 %{$arguments}
94b3529a 272 };
62728755 273
8cd017a8 274 # if we're debugging and/or the TIMER option is set, then we install
275 # Template::Timer as a custom CONTEXT object, but only if we haven't
276 # already got a custom CONTEXT defined
277
dccfa0ff 278 if ( $config->{TIMER} ) {
94b3529a 279 if ( $config->{CONTEXT} ) {
8cd017a8 280 $c->log->error(
281 'Cannot use Template::Timer - a TT CONFIG is already defined');
282 }
283 else {
94b3529a 284 $config->{CONTEXT} = Template::Timer->new(%$config);
8cd017a8 285 }
286 }
287
94b3529a 288 if ( $c->debug && $config->{DUMP_CONFIG} ) {
8cd017a8 289 use Data::Dumper;
94b3529a 290 $c->log->debug( "TT Config: ", Dumper($config) );
62728755 291 }
292
8cd017a8 293 return $class->NEXT::new(
294 $c,
295 {
94b3529a 296 template => Template->new($config) || do {
8cd017a8 297 my $error = Template->error();
298 $c->log->error($error);
299 $c->error($error);
300 return undef;
301 }
302 }
303 );
8077080c 304}
305
2774dc77 306=item process
8077080c 307
722fede4 308Renders the template specified in C<$c-E<gt>stash-E<gt>{template}> or
309C<$c-E<gt>request-E<gt>match>. Template variables are set up from the
310contents of C<$c-E<gt>stash>, augmented with C<base> set to
311C<$c-E<gt>req-E<gt>base>, C<c> to C<$c> and C<name> to
8cd017a8 312C<$c-E<gt>config-E<gt>{name}>. Alternately, the C<CATALYST_VAR>
313configuration item can be defined to specify the name of a template
314variable through which the context reference (C<$c>) can be accessed.
315In this case, the C<c>, C<base> and C<name> variables are omitted.
316Output is stored in C<$c-E<gt>response-E<gt>output>.
8077080c 317
318=cut
319
320sub process {
321 my ( $self, $c ) = @_;
23042c3c 322
323 my $template = $c->stash->{template} || $c->request->match;
324
325 unless ($template) {
8077080c 326 $c->log->debug('No template specified for rendering') if $c->debug;
327 return 0;
328 }
23042c3c 329
330 $c->log->debug(qq/Rendering template "$template"/) if $c->debug;
23042c3c 331
8cd017a8 332 my $output;
333 my $cvar = $self->config->{CATALYST_VAR};
334 my $vars = {
335 defined $cvar
336 ? ( $cvar => $c )
337 : (
338 c => $c,
339 base => $c->req->base,
340 name => $c->config->{name}
341 ),
342 %{ $c->stash() }
343 };
344
345 unless ( $self->template->process( $template, $vars, \$output ) ) {
8077080c 346 my $error = $self->template->error;
347 $error = qq/Couldn't render template "$error"/;
348 $c->log->error($error);
becb7ac2 349 $c->error($error);
23042c3c 350 return 0;
351 }
8cd017a8 352
23042c3c 353 unless ( $c->response->content_type ) {
354 $c->response->content_type('text/html; charset=utf-8');
8077080c 355 }
23042c3c 356
357 $c->response->body($output);
358
8077080c 359 return 1;
360}
361
2774dc77 362=item config
8077080c 363
8cd017a8 364This method allows your view subclass to pass additional settings to
365the TT configuration hash, or to set the C<CATALYST_VAR> and C<TIMER>
366options.
8077080c 367
2774dc77 368=back
8077080c 369
8cd017a8 370=head2 HELPERS
371
372The L<Catalyst::Helper::View::TT> and
373L<Catalyst::Helper::View::TTSite> helper modules are provided to create
374your view module. There are invoked by the F<myapp_create.pl> script:
375
376 $ script/myapp_create.pl view TT TT
377
378 $ script/myapp_create.pl view TT TTSite
379
380The L<Catalyst::Helper::View::TT> module creates a basic TT view
381module. The L<Catalyst::Helper::View::TTSite> module goes a little
382further. It also creates a default set of templates to get you
383started. It also configures the view module to locate the templates
384automatically.
385
8077080c 386=head1 SEE ALSO
387
8cd017a8 388L<Catalyst>, L<Catalyst::Helper::View::TT>,
389L<Catalyst::Helper::View::TTSite>, L<Template::Manual>
8077080c 390
c0eb0527 391=head1 AUTHORS
8077080c 392
393Sebastian Riedel, C<sri@cpan.org>
c0eb0527 394
d938377b 395Marcus Ramberg, C<mramberg@cpan.org>
c0eb0527 396
722fede4 397Jesse Sheidlower, C<jester@panix.com>
c0eb0527 398
8cd017a8 399Andy Wardley, C<abw@cpan.org>
8077080c 400
401=head1 COPYRIGHT
402
2774dc77 403This program is free software, you can redistribute it and/or modify it
404under the same terms as Perl itself.
8077080c 405
406=cut
407
4081;