Added default extension configuration option.
[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
8cd017a8 205
206The output generated by the template is stored in
207C<$c-E<gt>response-E<gt>output>.
208
209=head2 TEMPLATE PROFILING
210
caa61517 211=head2 METHODS
8077080c 212
2774dc77 213=over 4
214
215=item new
216
217The constructor for the TT view. Sets up the template provider,
218and reads the application config.
219
8077080c 220=cut
221
222sub new {
9300af5b 223 my ( $class, $c, $arguments ) = @_;
224
225 my $root = $c->config->{root};
226
94b3529a 227 my $config = {
caa61517 228 EVAL_PERL => 0,
4729c102 229 TEMPLATE_EXTENSION => '',
caa61517 230 INCLUDE_PATH => [ $root, "$root/base" ],
9300af5b 231 %{ $class->config },
8cd017a8 232 %{$arguments}
94b3529a 233 };
62728755 234
8cd017a8 235 # if we're debugging and/or the TIMER option is set, then we install
236 # Template::Timer as a custom CONTEXT object, but only if we haven't
237 # already got a custom CONTEXT defined
238
dccfa0ff 239 if ( $config->{TIMER} ) {
94b3529a 240 if ( $config->{CONTEXT} ) {
8cd017a8 241 $c->log->error(
242 'Cannot use Template::Timer - a TT CONFIG is already defined');
243 }
244 else {
94b3529a 245 $config->{CONTEXT} = Template::Timer->new(%$config);
8cd017a8 246 }
247 }
248
94b3529a 249 if ( $c->debug && $config->{DUMP_CONFIG} ) {
8cd017a8 250 use Data::Dumper;
94b3529a 251 $c->log->debug( "TT Config: ", Dumper($config) );
62728755 252 }
253
8cd017a8 254 return $class->NEXT::new(
255 $c,
256 {
94b3529a 257 template => Template->new($config) || do {
8cd017a8 258 my $error = Template->error();
259 $c->log->error($error);
260 $c->error($error);
261 return undef;
262 }
263 }
264 );
8077080c 265}
266
2774dc77 267=item process
8077080c 268
722fede4 269Renders the template specified in C<$c-E<gt>stash-E<gt>{template}> or
270C<$c-E<gt>request-E<gt>match>. Template variables are set up from the
271contents of C<$c-E<gt>stash>, augmented with C<base> set to
272C<$c-E<gt>req-E<gt>base>, C<c> to C<$c> and C<name> to
8cd017a8 273C<$c-E<gt>config-E<gt>{name}>. Alternately, the C<CATALYST_VAR>
274configuration item can be defined to specify the name of a template
275variable through which the context reference (C<$c>) can be accessed.
276In this case, the C<c>, C<base> and C<name> variables are omitted.
277Output is stored in C<$c-E<gt>response-E<gt>output>.
8077080c 278
279=cut
280
281sub process {
282 my ( $self, $c ) = @_;
23042c3c 283
4729c102 284 my $template = $c->stash->{template} || $c->request->match . $self->config->{TEMPLATE_EXTENSION};
23042c3c 285
286 unless ($template) {
8077080c 287 $c->log->debug('No template specified for rendering') if $c->debug;
288 return 0;
289 }
23042c3c 290
291 $c->log->debug(qq/Rendering template "$template"/) if $c->debug;
23042c3c 292
8cd017a8 293 my $output;
294 my $cvar = $self->config->{CATALYST_VAR};
295 my $vars = {
296 defined $cvar
297 ? ( $cvar => $c )
298 : (
299 c => $c,
300 base => $c->req->base,
301 name => $c->config->{name}
302 ),
303 %{ $c->stash() }
304 };
305
306 unless ( $self->template->process( $template, $vars, \$output ) ) {
8077080c 307 my $error = $self->template->error;
308 $error = qq/Couldn't render template "$error"/;
309 $c->log->error($error);
becb7ac2 310 $c->error($error);
23042c3c 311 return 0;
312 }
8cd017a8 313
23042c3c 314 unless ( $c->response->content_type ) {
315 $c->response->content_type('text/html; charset=utf-8');
8077080c 316 }
23042c3c 317
318 $c->response->body($output);
319
8077080c 320 return 1;
321}
322
2774dc77 323=item config
8077080c 324
8cd017a8 325This method allows your view subclass to pass additional settings to
4729c102 326the TT configuration hash, or to set the options as below:
327
328=over 2
329
330=item C<CATALYST_VAR>
331
332Allows you to change the name of the Catalyst context object. If set, it will also
333remove the base and name aliases, so you will have access them through <context>.
334
335For example:
336
337 MyApp->config({
338 name => 'MyApp',
339 root => $ROOT,
340 'V::TT' => {
341 CATALYST_VAR => 'Catalyst',
342 },
343 });
344
345F<message.tt2>:
346
347 The base is [% Catalyst.req.base %]
348 The name is [% Catalyst.config.name %]
349
350=item C<TIMER>
351
352If you have configured Catalyst for debug output, and turned on the TIMER setting,
353C<Catalyst::View::TT> will enable profiling of template processing
354(using L<Template::Timer>). This will embed HTML comments in the
355output from your templates, such as:
356
357 <!-- TIMER START: process mainmenu/mainmenu.ttml -->
358 <!-- TIMER START: include mainmenu/cssindex.tt -->
359 <!-- TIMER START: process mainmenu/cssindex.tt -->
360 <!-- TIMER END: process mainmenu/cssindex.tt (0.017279 seconds) -->
361 <!-- TIMER END: include mainmenu/cssindex.tt (0.017401 seconds) -->
362
363 ....
364
365 <!-- TIMER END: process mainmenu/footer.tt (0.003016 seconds) -->
366
367
368=item C<TEMPLATE_EXTENSION>
369
370an extension to add when looking for templates bases on the C<match> method in L<Catalyst::Request>.
371
372For example:
373
374 package MyApp::C::Test;
375 sub test : Local { .. }
376
377Would by default look for a template in <root>/test/test. If you set TEMPLATE_EXTENSION to '.tt', it will look for
378<root>/test/test.tt.
379
380=back
8077080c 381
2774dc77 382=back
8077080c 383
8cd017a8 384=head2 HELPERS
385
386The L<Catalyst::Helper::View::TT> and
387L<Catalyst::Helper::View::TTSite> helper modules are provided to create
388your view module. There are invoked by the F<myapp_create.pl> script:
389
390 $ script/myapp_create.pl view TT TT
391
392 $ script/myapp_create.pl view TT TTSite
393
394The L<Catalyst::Helper::View::TT> module creates a basic TT view
395module. The L<Catalyst::Helper::View::TTSite> module goes a little
396further. It also creates a default set of templates to get you
397started. It also configures the view module to locate the templates
398automatically.
399
8077080c 400=head1 SEE ALSO
401
8cd017a8 402L<Catalyst>, L<Catalyst::Helper::View::TT>,
403L<Catalyst::Helper::View::TTSite>, L<Template::Manual>
8077080c 404
c0eb0527 405=head1 AUTHORS
8077080c 406
407Sebastian Riedel, C<sri@cpan.org>
c0eb0527 408
d938377b 409Marcus Ramberg, C<mramberg@cpan.org>
c0eb0527 410
722fede4 411Jesse Sheidlower, C<jester@panix.com>
c0eb0527 412
8cd017a8 413Andy Wardley, C<abw@cpan.org>
8077080c 414
415=head1 COPYRIGHT
416
2774dc77 417This program is free software, you can redistribute it and/or modify it
418under the same terms as Perl itself.
8077080c 419
420=cut
421
4221;