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