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