File Coverage

blib/lib/Catalyst/View/Mason.pm
Criterion Covered Total %
statement 32 67 47.7
branch 0 16 0.0
condition 0 3 0.0
subroutine 8 11 72.7
pod 3 3 100.0
total 43 100 43.0


line stmt bran cond sub pod time code
1             package Catalyst::View::Mason;
2              
3 11     11   17559944 use strict;
  11         26  
  11         311  
4 11     11   46 use warnings;
  11         16  
  11         283  
5 11     11   46 use base qw/Catalyst::View/;
  11         21  
  11         4910  
6 11     11   542208 use Scalar::Util qw/blessed/;
  11         23  
  11         739  
7 11     11   55 use File::Spec;
  11         18  
  11         240  
8 11     11   6395 use HTML::Mason;
  11         669672  
  11         596  
9 11     11   128 use NEXT;
  11         27  
  11         6663  
10              
11             our $VERSION = '0.09_07';
12              
13             __PACKAGE__->mk_accessors('template');
14              
15             =head1 NAME
16              
17             Catalyst::View::Mason - Mason View Class
18              
19             =head1 SYNOPSIS
20              
21             # use the helper
22             script/create.pl view Mason Mason
23              
24             # lib/MyApp/View/Mason.pm
25             package MyApp::View::Mason;
26              
27             use base 'Catalyst::View::Mason';
28              
29             __PACKAGE__->config(use_match => 0);
30              
31             1;
32              
33             $c->forward('MyApp::View::Mason');
34              
35             =head1 DESCRIPTION
36              
37             Want to use a Mason component in your views? No problem!
38             Catalyst::View::Mason comes to the rescue.
39              
40             =head1 EXAMPLE
41              
42             From the Catalyst controller:
43              
44             $c->stash->{name} = 'Homer'; # Pass a scalar
45             $c->stash->{extra_info} = {
46             last_name => 'Simpson',
47             children => [qw(Bart Lisa Maggie)]
48             }; # A ref works too
49              
50             From the Mason template:
51              
52             <%args>
53             $name
54             $extra_info
55             </%args>
56             <p>Your name is <strong><% $name %> <% $extra_info->{last_name} %></strong>
57             <p>Your children are:
58             <ul>
59             % foreach my $child (@{$extra_info->{children}}) {
60             <li>$child
61             % }
62             </ul>
63              
64             =head1 METHODS
65              
66             =cut
67              
68             =head2 new($c, \%config)
69              
70             =cut
71              
72             sub new {
73 10     10 1 67433 my ($self, $c, $arguments) = @_;
74              
75             my %config = (
76             comp_root => $c->config->{root} . q//, # stringify
77             data_dir => File::Spec->tmpdir,
78             use_match => 1,
79             allow_globals => [],
80             template_extension => q//,
81 10         2046 %{ $self->config },
82 10         51 %{ $arguments },
  10         546  
83             );
84              
85 10         37 unshift @{ $config{allow_globals} }, qw/$c $base $name/;
  10         45  
86 10         217 $self = $self->NEXT::new($c, \%config);
87 10         20050 $self->{output} = q//;
88              
89 10         84 $self->config({ %config });
90              
91 10         966 delete @config{qw/use_match template_extension/};
92              
93             $self->template(
94             HTML::Mason::Interp->new(
95             %config,
96             out_method => \$self->{output},
97             )
98 10         140 );
99              
100 0           return $self;
101             }
102              
103             =head2 process
104              
105             Renders the component specified in $c->stash->{template} or $c->request->match
106             or $c->action (depending on the use_match setting) to $c->response->body.
107              
108             Note that the component name must be absolute, or is converted to absolute
109             (i.e., a / is added to the beginning if it doesn't start with one).
110              
111             Mason global variables C<$base>, C<$c>, and C<$name> are automatically
112             set to the base, context, and name of the app, respectively.
113              
114             =cut
115              
116             sub process {
117 0     0 1   my ($self, $c) = @_;
118              
119 0           my $component_path = $c->stash->{template};
120            
121 0 0         unless ($component_path) {
122             $component_path = $self->config->{use_match}
123 0 0         ? $c->request->match
124             : $c->action;
125              
126 0           $component_path .= $self->config->{template_extension};
127             }
128              
129 0           my $output = $self->render($c, $component_path);
130              
131 0 0 0       if (blessed($output) && $output->isa('HTML::Mason::Exception')) {
132 0           chomp $output;
133 0           my $error = qq/Couldn't render component "$component_path" - error was "$output"/;
134 0           $c->log->error($error);
135 0           $c->error($error);
136 0           return 0;
137             }
138              
139 0 0         unless ($c->response->content_type) {
140 0           $c->response->content_type('text/html; charset=utf-8');
141             }
142              
143 0           $c->response->body($output);
144              
145 0           return 1;
146             }
147              
148             =head2 render($c, $component_path, \%args)
149              
150             Renders the given template and returns output, or a HTML::Mason::Exception
151             object upon error.
152              
153             The template variables are set to %$args if $args is a hashref, or
154             $c-E<gt>stash otherwise.
155              
156             =cut
157              
158             sub _default_globals {
159 0     0     my ($self, $c) = @_;
160              
161             my %default_globals = (
162             '$c' => $c,
163             '$base' => $c->request->base,
164             '$name' => $c->config->{name},
165 0           );
166              
167 0           return %default_globals;
168             }
169              
170             sub render {
171 0     0 1   my ($self, $c, $component_path, $args) = @_;
172              
173 0 0         if ($component_path !~ m{^/}) {
174 0           $component_path = '/' . $component_path;
175             }
176              
177 0 0         $c->log->debug(qq/Rendering component "$component_path"/) if $c->debug;
178              
179             # Set the URL base, context and name of the app as global Mason vars
180             # $base, $c and $name
181 0           my %default_globals = $self->_default_globals($c);
182 0           while (my ($key, $val) = each %default_globals) {
183 0           $self->template->set_global($key => $val);
184             }
185              
186 0           $self->{output} = q//;
187              
188 0           eval {
189             $self->template->exec(
190             $component_path,
191 0 0         ref $args eq 'HASH' ? %{ $args } : %{ $c->stash },
  0            
  0            
192             );
193             };
194              
195 0 0         if (my $error = $@) {
196 0           return $error;
197             }
198              
199 0           return $self->{output};
200             }
201              
202             =head3 config
203              
204             This allows you to to pass additional settings to the HTML::Mason::Interp
205             constructor or to set the options as below:
206              
207             =over
208              
209             =item C<use_match>
210              
211             Use C<$c-E<gt>request-E<gt>match> instead of C<$c-E<gt>action> to determine
212             which template to use if C<$c-E<gt>stash-E<gt>{template}> isn't set. This option
213             is deprecated and exists for backward compatibility only.
214              
215             Currently defaults to 1.
216              
217             =back
218              
219             The default HTML::Mason::Interp config options are as follows:
220              
221             =over
222              
223             =item C<comp_root>
224              
225             C<$c-E<gt>config-E<gt>root>
226              
227             =item C<data_dir>
228              
229             C<File::Spec-E<gt>tmpdir>
230              
231             =item C<allow_globals>
232              
233             C<qw/$c $name $base/>
234              
235             If you add additional allowed globals those will be appended to the list of
236             default globals.
237              
238             =back
239              
240             =cut
241              
242             =head1 SEE ALSO
243              
244             L<Catalyst>, L<HTML::Mason>, "Using Mason from a Standalone Script" in L<HTML::Mason::Admin>
245              
246             =head1 AUTHOR
247              
248             Andres Kievsky C<ank@cpan.org>
249             Sebastian Riedel C<sri@cpan.org>
250             Marcus Ramberg
251             Florian Ragwitz <rafl@debian.org>
252              
253             =head1 COPYRIGHT
254              
255             This program is free software, you can redistribute it and/or modify it under
256             the same terms as Perl itself.
257              
258             =cut
259              
260             1;