Move View::TT to new repo layout.
[catagits/Catalyst-View-TT.git] / tags / 0.13 / lib / Catalyst / View / TT.pm
CommitLineData
cbe7e4d8 1package Catalyst::View::TT;
2
3use strict;
4use base qw/Catalyst::Base/;
5use Template;
6use Template::Timer;
7use NEXT;
8
9our $VERSION = '0.13';
10
11__PACKAGE__->mk_accessors('template');
12
13=head1 NAME
14
15Catalyst::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 our $ROOT = '/home/dent/catalyst/MyApp';
25
26 MyApp->config({
27 name => 'MyApp',
28 root => $ROOT,
29 'MyApp::V::TT' => {
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 {
47 my ( $self, $c ) = @_;
48 $c->stash->{template} = 'message.tt2';
49 $c->stash->{message} = 'Hello World!';
50 $c->forward('MyApp::V::TT');
51 }
52
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';
86
87 __PACKAGE__->config->{DEBUG} = 'all';
88
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.
93
94 # In MyApp or MyApp::Controller::SomeController
95
96 sub end : Private {
97 my( $self, $c ) = @_;
98 $c->forward('MyApp::V::TT');
99 }
100
101=head2 CONFIGURATION
102
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.
106
107 package MyApp::V::TT;
108
109 use strict;
110 use base 'Catalyst::View::TT';
111
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
136The final, and perhaps most direct way, is to define a class
137item in your main application configuration, again by calling the
138uniquitous C<config()> method. The items in the class hash are
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,
154 'MyApp::V::TT' => {
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 {
171 my ( $self, $c ) = @_;
172 $c->stash->{template} = 'message.tt2';
173 $c->forward('MyApp::V::TT');
174 }
175
176If a class item isn't defined, then it instead uses the
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 {
185 my ( $self, $c ) = @_;
186 $c->stash->{template} = 'message.tt2';
187 $c->stash->{message} = 'Hello World!';
188 $c->forward('MyApp::V::TT');
189 }
190
191A number of other template variables are also added:
192
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,
212 'MyApp::V::TT' => {
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:
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
242You can suppress template profiling by setting the C<TIMER> configuration
243item to a false value.
244
245 MyApp->config({
246 'MyApp::V::TT' => {
247 TIMER => 0,
248 },
249 });
250
251=head2 METHODS
252
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
260=cut
261
262sub new {
263 my ( $class, $c, $arguments ) = @_;
264
265 my $root = $c->config->{root};
266
267 my $config = {
268 EVAL_PERL => 0,
269 INCLUDE_PATH => [ $root, "$root/base" ],
270 %{ $class->config },
271 %{$arguments}
272 };
273
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
278 if ( $config->{TIMER} || ( $c->debug() && !exists $config->{TIMER} ) ) {
279 if ( $config->{CONTEXT} ) {
280 $c->log->error(
281 'Cannot use Template::Timer - a TT CONFIG is already defined');
282 }
283 else {
284 $config->{CONTEXT} = Template::Timer->new(%$config);
285 }
286 }
287
288 if ( $c->debug && $config->{DUMP_CONFIG} ) {
289 use Data::Dumper;
290 $c->log->debug( "TT Config: ", Dumper($config) );
291 }
292
293 return $class->NEXT::new(
294 $c,
295 {
296 template => Template->new($config) || do {
297 my $error = Template->error();
298 $c->log->error($error);
299 $c->error($error);
300 return undef;
301 }
302 }
303 );
304}
305
306=item process
307
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
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>.
317
318=cut
319
320sub process {
321 my ( $self, $c ) = @_;
322
323 my $template = $c->stash->{template} || $c->request->match;
324
325 unless ($template) {
326 $c->log->debug('No template specified for rendering') if $c->debug;
327 return 0;
328 }
329
330 $c->log->debug(qq/Rendering template "$template"/) if $c->debug;
331
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 ) ) {
346 my $error = $self->template->error;
347 $error = qq/Couldn't render template "$error"/;
348 $c->log->error($error);
349 $c->error($error);
350 return 0;
351 }
352
353 unless ( $c->response->content_type ) {
354 $c->response->content_type('text/html; charset=utf-8');
355 }
356
357 $c->response->body($output);
358
359 return 1;
360}
361
362=item config
363
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.
367
368=back
369
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
386=head1 SEE ALSO
387
388L<Catalyst>, L<Catalyst::Helper::View::TT>,
389L<Catalyst::Helper::View::TTSite>, L<Template::Manual>
390
391=head1 AUTHORS
392
393Sebastian Riedel, C<sri@cpan.org>
394
395Marcus Ramberg, C<mramberg@cpan.org>
396
397Jesse Sheidlower, C<jester@panix.com>
398
399Andy Wardley, C<abw@cpan.org>
400
401=head1 COPYRIGHT
402
403This program is free software, you can redistribute it and/or modify it
404under the same terms as Perl itself.
405
406=cut
407
4081;