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