File Coverage

blib/lib/Catalyst/View/Template/Pure/Helpers.pm
Criterion Covered Total %
statement 45 62 72.5
branch 14 28 50.0
condition 3 6 50.0
subroutine 6 10 60.0
pod 3 3 100.0
total 71 109 65.1


line stmt bran cond sub pod time code
1 1     1   404539 use strict;
  1         2  
  1         27  
2 1     1   3 use warnings;
  1         1  
  1         38  
3              
4             package Catalyst::View::Template::Pure::Helpers;
5              
6 1     1   4 use Exporter 'import';
  1         5  
  1         27  
7 1     1   554 use Template::Pure::DataProxy;
  1         518  
  1         773  
8              
9             our @EXPORT_OK = (qw/Uri Apply Wrap/);
10             our %EXPORT_TAGS = (All => \@EXPORT_OK, ALL => \@EXPORT_OK);
11              
12             sub Uri {
13 2     2 1 17673 my ($path, @args) = @_;
14 2 50       9 die "$path is not a string" unless ref \$path eq 'SCALAR';
15              
16             # What type of path? Controller.action_name or relative action/namespace
17 2         3 my ($controller_proto, $action_proto) = ();
18 2 50       5 if($path=~m/^(.*)\.(.+)$/) {
19 0         0 ($controller_proto, $action_proto) = ($1,$2);
20             } else {
21             # probably namespace
22 2         3 $action_proto = $path;
23             }
24              
25             return sub {
26 2     2   2930 my ($pure, $dom, $data) = @_;
27 2         6 my $c = $pure->{view}{ctx};
28 2         1 my $controller;
29 2 50       5 if($controller_proto) {
30 0 0       0 die "$controller_proto is not a controller!" unless
31             $controller = $c->controller($controller_proto);
32             } else {
33             # if not specified, use the current
34 2         10 $controller = $c->controller;
35             }
36              
37 2         173 my $action = '';
38 2 100       11 if(my ($data_path) = ($action_proto=~m/^\=\{(.+)\}$/)) {
    50          
39 1         4 $action = $pure->data_at_path($data,$data_path);
40             }
41             elsif($action_proto =~/\//) {
42             # proto is a relative action namespace.
43 0 0       0 my $path = $action_proto=~m/^\// ? $action_proto : $controller->action_for($action_proto)->private_path;
44 0 0       0 die "$action_proto is not an action for controller ${\$controller->component_name}" unless $path;
  0         0  
45 0 0       0 die "$path is not a private path"
46             unless $action = $c->dispatcher->get_action_by_path($path);
47             } else {
48 1 50       6 die "$action_proto is not an action for controller ${\$controller->component_name}"
  0         0  
49             unless $action = $controller->action_for($action_proto);
50             }
51              
52 2   50     329 $data = Template::Pure::DataProxy->new(
      50        
      50        
53             $data,
54             captures => $c->request->captures || [],
55             args => $c->request->args || [],
56             query => $c->request->query_parameters|| +{});
57              
58             # We need to unroll the @args and fill in any template values.
59             my $resolve = sub {
60 7         8 my $arg = shift;
61 7 100       17 if(my ($v) = ($arg=~m/^\=\{(.+)\}$/)) {
62 4         10 return $pure->data_at_path($data,$v);
63             } else {
64 3         6 return $arg;
65             }
66 2         265 };
67              
68             # Change any placeholders.
69             my @local_args = map {
70 2         5 my $arg = $_;
  4         4  
71 4 100       17 if(ref \$_ eq 'SCALAR') {
    100          
    50          
72 1         3 $arg = $resolve->($arg);
73             } elsif(ref $arg eq 'ARRAY') {
74 2         2 $arg = [map { $resolve->($_) } @$arg];
  2         4  
75             } elsif(ref $arg eq 'HASH') {
76 1         3 $arg = +{map { my $val = $arg->{$_}; $resolve->($_) => $resolve->($val) } keys %$arg};
  2         105  
  2         4  
77             }
78 4         344 $arg;
79             } @args;
80              
81 2         11 my $uri = $c->uri_for($action, @local_args);
82 2         4061 return $pure->encoded_string("$uri");
83 2         22 };
84             }
85              
86             sub Apply {
87 0     0 1   my ($view_name, @args) = @_;
88             return sub {
89 0     0     my ($pure, $dom, $data) = @_;
90 0           my $c = $pure->{view}{ctx};
91 0           return $c->view($view_name, $data, template=>$dom, clear_stash=>1, @args);
92 0           };
93             }
94              
95             sub Wrap {
96 0     0 1   my ($view_name, @args) = @_;
97             return sub {
98 0     0     my ($pure, $dom, $data) = @_;
99 0           my $c = $pure->{view}{ctx};
100 0           return $c->view($view_name, $data, content=>$dom, clear_stash=>1, @args);
101 0           };
102             }
103              
104             1;
105              
106             =head1 NAME
107            
108             Catalyst::View::Template::Pure::Helpers - Simplify some boilerplate
109              
110             =head1 SYNOPSIS
111            
112             package MyApp::View::Story;
113              
114             use Moose;
115             use Catalyst::View::Template::Pure::Helpers (':ALL');
116             extends 'Catalyst::View::Template::Pure';
117              
118             has [qw/title body capture arg q/] => (is=>'ro', required=>1);
119              
120             __PACKAGE__->config(
121             returns_status => [200],
122             template => q[
123             <!doctype html>
124             <html lang="en">
125             <head>
126             <title>Title Goes Here</title>
127             </head>
128             <body>
129             <a name="hello">hello</a>
130             </body>
131             </html>
132             ],
133             directives => [
134              
135             'a[name="hello"]@href' => Uri('Story.last',['={year}'], '={id}', {q=>'={q}',rows=>5}),
136             ],
137             );
138            
139             =head1 DESCRIPTION
140              
141             Generates code for some common tasks you need to do in your templates, such
142             as build URLs etc.
143              
144             =head2 Uri
145              
146             Used to generate a URL via $c->uri_for. Takes signatures like:
147              
148             Uri("$controller.$action", \@captures, @args, \%query)
149             Uri(".$action", \@captures, @args, \%query)
150             Uri("$relative_action_private_name", \@captures, @args, \%query)
151             Uri("$absolute_action_private_name", \@captures, @args, \%query)
152              
153             We fill placeholders in the arguments in the same was as in templates, for example:
154              
155             Uri('Story.last',['={year}'], '={id}', {q=>'={q}',rows=>5})
156              
157             Would fill year, id and q from the current data context. We also merge in the following
158             keys to the current data context:
159              
160             captures => $c->request->captures,
161             args => $c->request->args,
162             query => $c->request->query_parameters;
163              
164             To make it easier to fill data from the current request. For example:
165              
166             Uri('last', ['={captures}'], '={args}')
167              
168             You can also use data paths placeholders to indicate the action on which we are building
169             a URI:
170              
171             Uri('={delete_link}', ['={captures}'], '={args}')
172              
173             In this case the placeholder should refer to a L<Catalyst::Action> object, not a string:
174              
175             $c->view('List', delete_link => $self->action_for('item/delete'));
176              
177             This may change in a future version.
178              
179             =over
180              
181             =item Uri("$controller.$action", \@captures, @args, \%query)
182              
183             URI for an action at a specific Controller. '$controller' should be
184             a controller namespace part, for example 'MyApp::Controller::User' would
185             be 'User' and 'MyApp::Controller::User::Info' would be 'User::Info'.
186              
187             =item Uri(".$action", \@captures, @args, \%query)
188              
189             Relative version of the previous helper. Set the controller to the
190             current controller.
191              
192             =item Uri("$absolute_action_private_name", \@captures, @args, \%query)
193              
194             Creates a URI for an absolute action namespace. Examples:
195              
196             Uri('/root/user')
197              
198             =item Uri("$relative_action_private_name", \@captures, @args, \%query)
199              
200             Creates a URI for a relative (under the current controller namespace)
201             action namespace. Examples:
202              
203             Uri('user/info')
204              
205             =back
206              
207             =head2 Apply
208              
209             Takes a view name and optionally arguments that are passed to ->new. Used to
210             apply a view over the results of a previous one, allowing for chained views.
211              
212             'ul.todo-list li' => {
213             '.<-tasks' => Apply('Summary::Task'),
214             },
215              
216             Useful when you wish to delegate the job of processing a section of the template
217             to a different view, but you don't need a full include.
218              
219             =head2 Wrap
220              
221             Used to pass the response on a template to another template, via a 'content'
222             argument. Similar to the 'wrapper' processing instruction.
223              
224             =head1 SEE ALSO
225            
226             L<Template::Pure>, L<Catalyst::View::Template::Pure>
227            
228             =head1 AUTHOR
229            
230             John Napiorkowski L<email:jjnapiork@cpan.org>
231            
232             =head1 COPYRIGHT & LICENSE
233            
234             Please see L<Catalyst::View::Template::Pure>> for copyright and license information.
235