File Coverage

blib/lib/Catalyst/View/Template/Lace.pm
Criterion Covered Total %
statement 28 43 65.1
branch 1 8 12.5
condition 4 9 44.4
subroutine 7 8 87.5
pod n/a
total 40 68 58.8


line stmt bran cond sub pod time code
1             package Catalyst::View::Template::Lace;
2              
3             our $VERSION = '0.009';
4              
5 1     1   2515748 use Module::Runtime;
  1         2  
  1         8  
6 1     1   312 use Catalyst::View::Template::Lace::Renderer;
  1         3  
  1         44  
7 1     1   330 use Template::Lace::Utils;
  1         34821  
  1         55  
8 1     1   10 use Moo;
  1         3  
  1         11  
9              
10             extends 'Catalyst::View';
11              
12             sub COMPONENT {
13 10     10   185660 my ($class, $app, $args) = @_;
14 10         82 my $merged_args = $class->merge_config_hashes($class->config, $args);
15             my $merged_component_handlers = $class->merge_config_hashes(
16 10   100     113746 (delete($merged_args->{component_handlers})||+{}),
17             $class->view_components($app, $merged_args));
18              
19 10   50     841 my $adaptor = delete($merged_args->{factory}) || 'Catalyst::View::Template::Lace::Factory';
20 10   33     63 my $model_class = delete($merged_args->{model_class}) || $class;
21 10         92 my %args = (
22             model_class=>$model_class,
23             renderer_class=>'Catalyst::View::Template::Lace::Renderer',
24             component_handlers=>$merged_component_handlers,
25             init_args=>+{ %$merged_args, app=>$app },
26             );
27              
28             $args{model_constructor} = delete($merged_args->{model_constructor})
29 10 50       48 if $merged_args->{model_constructor};
30              
31 10         49 my $factory = Module::Runtime::use_module($adaptor)->new(%args);
32 10         86334 return $factory;
33             }
34              
35             has ctx => (is=>'ro', required=>0);
36              
37             sub view_components {
38 10     10   51 my ($class, $app, $merged_args) = @_;
39             return +{
40             catalyst => {
41             subrequest => Template::Lace::Utils::mk_component {
42 0     0   0 require HTTP::Request;
43 0         0 require HTTP::Message::PSGI;
44              
45 0         0 my @args = (delete $_{action});
46 0   0     0 my $method = ((delete $_{method}) || 'GET');
47 0 0       0 push @args, delete($_{parts}) if $_{parts};
48 0 0       0 push @args, delete($_{query}) if $_{query};
49              
50 0         0 my $href = $_{model}->uri_for(@args);
51 0         0 my $http_request = HTTP::Request->new($method, $href);
52 0         0 my $psgi_env = HTTP::Message::PSGI::req_to_psgi($http_request);
53 0         0 my $psgi_response = $_{model}->ctx->psgi_app->($psgi_env);
54 0         0 my $http_response = HTTP::Message::PSGI::res_from_psgi($psgi_response);
55 0         0 my $content = $http_response->content;
56 0 0       0 if($_{at}) {
57 0         0 return $_->make_dom($content)->at($_{at});
58             }
59 0         0 return $content;
60             }
61             },
62             view => sub {
63 5     5   36903 my ($name, $args, %attrs) = @_;
64             my $view_name = join '::', map {
65 5         25 $_=~s/[_-]([a-z])/\u$1/g;
  5         18  
66 5         24 ucfirst $_;
67             } split '-', $name;
68 5         37 return $app->view($view_name);
69             },
70 10         126 };
71             }
72              
73             1;
74              
75             =head1 NAME
76              
77             Catalyst::View::Template::Lace - Catalyst View Adaptor for Template::Lace
78              
79             =head1 SYNOPSIS
80              
81             Define a View:
82              
83             package MyApp::View::User;
84              
85             use Moo;
86             extends 'Catalyst::View::Template::Lace';
87              
88             has [qw/age name motto/] => (is=>'ro', required=>1);
89              
90             sub template {q[
91             <html>
92             <head>
93             <title>User Info</title>
94             </head>
95             <body>
96             <dl id='user'>
97             <dt>Name</dt>
98             <dd id='name'>NAME</dd>
99             <dt>Age</dt>
100             <dd id='age'>AGE</dd>
101             <dt>Motto</dt>
102             <dd id='motto'>MOTTO</dd>
103             </dl>
104             </body>
105             </html>
106             ]}
107              
108             sub process_dom {
109             my ($self, $dom) = @_;
110             $dom->dl('#user', +{
111             age=>$self->age,
112             name=>$self->name,
113             motto=>$self->motto});
114             }
115              
116             1;
117              
118             Used in a controller:
119              
120             package MyApp::Controller::User;
121              
122             use Moose;
123             use MooseX::MethodAttributes;
124             extends 'Catalyst::Controller';
125              
126             sub display :Path('') {
127             my ($self, $c) = @_;
128             $c->view('User',
129             name => 'John',
130             age => 42,
131             motto => 'Why Not?')
132             ->http_ok;
133             }
134              
135             __PACKAGE__->meta->make_immutable;
136              
137             A Template may also contain components which are reusable blocks of template
138             functionality and which refer to other Catalyst Views in your application:
139              
140             <view-master title='Homepage'>
141             <view-header navbar_section='home'/>
142             <section>
143             <p>You are doomed to discover you can never recover from the narcolyptic
144             country in which you once stood, where the fires alway burning but there's
145             never enough wood</p>
146             </section>
147             <view-footer copyright='$.copy' />
148             </view-master>
149              
150             Such components can wrap your main content or even other component, and they can
151             accept arguments. See L<Catalyst::View::Template::Lace::Tutorial> for more details.
152              
153             =head1 DESCRIPTION
154              
155             B<NOTE> I consider this an early access release. Code and API here is subject
156             to significant change as needed to advance the project. Please don't use this
157             in production unless you are willing to cope with that.
158              
159             L<Catalyst::View::Template::Lace> is a view adaptor for L<Template::Lace> with
160             some L<Catalyst> specific helpers and features added. Reviewing documentation
161             for L<Template::Lace> would useful in furthering your ability to use it in
162             L<Catalyst>.
163              
164             In short, this is a template framework for L<Catalyst> that introduces strongly
165             typed views and view components as design patterns for your web applications.
166             What this means is that unlike most L<Catalyst> views that you're probably
167             familiar with (such as the Template::Toolkit view) we define one view per
168             template instead of one view for all the templates. Although this might seem
169             like a lot of views to write the upside is by defining a strong interface for your
170             view, you eliminate a host of display errors that I commonly see with existing views
171             since there is no contract beween a view and the controller that is calling it. For
172             example a typo in setting the stash can turn into a hard to track down bug in the
173             template. Also since each component in your view has access to the L<Catalyst> context, you can
174             write smarter views with display logic properly encapsulated near the template
175             code it will actually be used. This reduces complexity in your controllers and
176             makes it easier to solve complex layout logic.
177              
178             After reviewing this documentation you can advance to L<Catalyst::View::Template::Lace::Tutorial>
179             and you might find the test cases in the C</t> directory of this distribution
180             handy as well.
181              
182             B<NOTE> I consider current documentation to be the 'thin red line' requirement
183             for CPAN publication but there's tons more to be done. Critique and contributions
184             very welcomed!.
185              
186             =head1 CONFIGURATION
187              
188             This component defines the following configuration options:
189              
190             =head2 factory
191              
192             These specifies which subclass of L<Template::Lace::Factory> will be used to
193             manage your view lifecycle. The default is L<Catalyst::View::Template::Lace::Factory>.
194             You can also specify L<Catalyst::View::Template::Lace::PerContext> or write your
195             own. See documentation for the two options for more.
196              
197             =head2 model_class
198              
199             =head2 render_class
200              
201             =head2 init_args
202              
203             =head2 model_constructor
204              
205             =head2 component_handlers
206              
207             All these are pass through configuration to the underlying subclass of
208             L<Template::Lace::Factory> which you should review.
209              
210             =head1 AUTHOR
211            
212             John Napiorkowski L<email:jjnapiork@cpan.org>
213            
214             =head1 SEE ALSO
215            
216             L<Template::Lace>, L<Catalyst::View::Template::Pure>
217              
218             =head1 COPYRIGHT & LICENSE
219            
220             Copyright 2017, John Napiorkowski L<email:jjnapiork@cpan.org>
221            
222             This library is free software; you can redistribute it and/or modify it under
223             the same terms as Perl itself.
224              
225             =cut