Commit | Line | Data |
30726632 |
1 | package Catalyst::View::Component::SubInclude; |
2 | use Moose::Role; |
3 | |
4 | use Carp qw/croak/; |
7094e990 |
5 | use Catalyst::Utils (); |
956a83d8 |
6 | use Class::MOP (); |
7 | use MooseX::Types::Moose qw/Str HashRef/; |
f91a7d21 |
8 | use namespace::clean -except => 'meta'; |
30726632 |
9 | |
d547aa95 |
10 | with 'Catalyst::Component::ContextClosure'; |
11 | |
ada1ae3c |
12 | =head1 NAME |
13 | |
14 | Catalyst::View::Component::SubInclude - Use subincludes in your Catalyst views |
15 | |
16 | =head1 VERSION |
17 | |
e02835f5 |
18 | Version 0.11 |
ada1ae3c |
19 | |
20 | =cut |
21 | |
e02835f5 |
22 | our $VERSION = '0.11'; |
cc37b7b3 |
23 | $VERSION = eval $VERSION; |
ada1ae3c |
24 | |
25 | =head1 SYNOPSIS |
26 | |
27 | package MyApp::View::TT; |
28 | use Moose; |
29 | |
30 | extends 'Catalyst::View::TT'; |
31 | with 'Catalyst::View::Component::SubInclude'; |
32 | |
33 | __PACKAGE__->config( subinclude_plugin => 'SubRequest' ); |
34 | |
35 | Then, somewhere in your templates: |
36 | |
37 | [% subinclude('/my/widget') %] |
be2a019a |
38 | [% subinclude_using('SubRequest', '/page/footer') %] |
ada1ae3c |
39 | |
40 | =head1 DESCRIPTION |
41 | |
42 | C<Catalyst::View::Component::SubInclude> allows you to include content in your |
43 | templates (or, more generally, somewhere in your view's C<render> processing) |
f81dfa28 |
44 | which comes from another action in your application. It's implemented as a |
4e327756 |
45 | L<Moose::Role|Moose::Role>, so using L<Moose|Moose> in your view is required. |
ada1ae3c |
46 | |
47 | Simply put, it's a way to include the output of a Catalyst sub-request somewhere |
f81dfa28 |
48 | in your page. |
ada1ae3c |
49 | |
6bd0988d |
50 | It's built in an extensible way so that you're free to use sub-requests, |
51 | Varnish ESI (L<http://www.catalystframework.org/calendar/2008/17>) or any other |
1152381d |
52 | sub-include plugin you might want to implement. |
ada1ae3c |
53 | |
be2a019a |
54 | =head1 STASH FUNCTIONS |
ada1ae3c |
55 | |
56 | This component does its magic by exporting a C<subinclude> coderef entry to the |
f81dfa28 |
57 | stash. This way, it's easily accessible by the templates (which is the most |
ada1ae3c |
58 | common use-case). |
59 | |
60 | =head2 C<subinclude( $path, @args )> |
61 | |
f81dfa28 |
62 | This will render and return the body of the included resource (as specified by |
be2a019a |
63 | C<$path>) using the default subinclude plugin. |
64 | |
65 | =head2 C<subinclude_using( $plugin, $path, @args )> |
66 | |
f81dfa28 |
67 | This will render and return the body of the included resource (as specified by |
be2a019a |
68 | C<$path>) using the specified subinclude plugin. |
69 | |
f81dfa28 |
70 | The C<subinclude> function above is implemented basically as a shortcut which |
be2a019a |
71 | calls this function using the default plugin as the first parameter. |
ada1ae3c |
72 | |
73 | =head1 SUBINCLUDE PLUGINS |
74 | |
788d0e72 |
75 | The module comes with several subinclude plugins: |
76 | L<SubRequest|Catalyst::View::Component::SubInclude::SubRequest>, |
77 | L<HTTP|Catalyst::View::Component::SubInclude::HTTP>, |
78 | L<SSI|Catalyst::View::Component::SubInclude::SSI>, |
79 | L<Visit|Catalyst::View::Component::SubInclude::Visit> and |
80 | L<ESI|Catalyst::View::Component::SubInclude::ESI>. |
ada1ae3c |
81 | |
f81dfa28 |
82 | By default, the C<SubRequest> plugin will be used. This can be changed in the |
ada1ae3c |
83 | view's configuration options (either in the config file or in the view module |
f81dfa28 |
84 | itself). |
ada1ae3c |
85 | |
4162256a |
86 | __PACKAGE__->config( |
87 | subinclude_plugin => 'ESI', |
88 | subinclude => { |
89 | 'SubRequest' => { |
90 | keep_stash => 1, |
91 | }, |
92 | 'HTTP::POST' => { |
93 | class => 'HTTP', |
94 | http_method => 'POST', |
95 | ua_timeout => '10', |
96 | uri_map => { |
97 | '/foo/' => 'http://www.foo.com/', |
98 | }, |
99 | }, |
100 | }, |
101 | ); |
102 | |
103 | You can change each plugins' configuration through the keys in the 'subinclude' |
104 | config key (example above) |
ada1ae3c |
105 | |
be2a019a |
106 | =head2 C<set_subinclude_plugin( $plugin )> |
107 | |
108 | This method changes the current active subinclude plugin in runtime. It expects |
f81dfa28 |
109 | the plugin suffix (e.g. C<ESI> or C<SubRequest>) or a fully-qualified class |
be2a019a |
110 | name in the C<Catalyst::View::Component::SubInclude> namespace. |
111 | |
112 | =head2 Writing plugins |
113 | |
f81dfa28 |
114 | If writing your own plugin, keep in kind plugins are required to implement a |
11a93ea1 |
115 | class method C<generate_subinclude> with the following signature: |
116 | |
117 | sub generate_subinclude { |
118 | my ($class, $c, @args) = @_; |
119 | } |
120 | |
be2a019a |
121 | The default plugin is stored in the C<subinclude_plugin> which can be changed |
122 | in runtime. It expects a fully qualified class name. |
123 | |
ada1ae3c |
124 | =cut |
125 | |
30726632 |
126 | has 'subinclude_plugin' => ( |
127 | is => 'rw', |
956a83d8 |
128 | isa => Str, |
be2a019a |
129 | ); |
30726632 |
130 | |
35ebe0b6 |
131 | has subinclude => ( |
132 | is => 'ro', |
133 | isa => HashRef, |
134 | default => sub { {} }, |
135 | ); |
136 | |
30726632 |
137 | around 'new' => sub { |
138 | my $next = shift; |
139 | my $class = shift; |
f81dfa28 |
140 | |
30726632 |
141 | my $self = $class->$next( @_ ); |
f81dfa28 |
142 | |
30726632 |
143 | my $subinclude_plugin = $self->config->{subinclude_plugin} || 'SubRequest'; |
be2a019a |
144 | $self->set_subinclude_plugin( $subinclude_plugin ); |
f81dfa28 |
145 | |
30726632 |
146 | $self; |
147 | }; |
148 | |
1869d781 |
149 | before 'render' => sub { |
30726632 |
150 | my ($self, $c, @args) = @_; |
ab0b6bbd |
151 | |
d547aa95 |
152 | $c->stash->{subinclude} = $self->make_context_closure(sub { $self->_subinclude( @_ ) }, $c); |
153 | $c->stash->{subinclude_using} = $self->make_context_closure(sub { $self->_subinclude_using( @_ ) }, $c); |
30726632 |
154 | }; |
155 | |
be2a019a |
156 | sub set_subinclude_plugin { |
157 | my ($self, $plugin) = @_; |
158 | |
956a83d8 |
159 | my $subinclude_class = blessed $self->_subinclude_plugin_class_instance( $plugin ); |
be2a019a |
160 | $self->subinclude_plugin( $subinclude_class ); |
161 | } |
162 | |
163 | sub _subinclude { |
164 | my ($self, $c, @args) = @_; |
165 | $self->_subinclude_using( $c, $self->subinclude_plugin, @args ); |
166 | } |
167 | |
168 | sub _subinclude_using { |
169 | my ($self, $c, $plugin, @args) = @_; |
956a83d8 |
170 | $plugin = $self->_subinclude_plugin_class_instance($plugin); |
171 | $plugin->generate_subinclude( $c, @args ); |
be2a019a |
172 | } |
173 | |
956a83d8 |
174 | has _subinclude_plugin_class_instance_cache => ( |
175 | isa => HashRef, |
176 | is => 'ro', |
177 | default => sub { {} }, |
178 | ); |
179 | |
180 | sub _subinclude_plugin_class_instance { |
be2a019a |
181 | my ($self, $plugin) = @_; |
f81dfa28 |
182 | |
956a83d8 |
183 | my $cache = $self->_subinclude_plugin_class_instance_cache; |
184 | return $cache->{$plugin} if exists $cache->{$plugin}; |
be2a019a |
185 | |
956a83d8 |
186 | my $plugin_config = Catalyst::Utils::merge_hashes( |
35ebe0b6 |
187 | $self->subinclude->{ALL}||{}, |
188 | $self->subinclude->{$plugin}||{} |
956a83d8 |
189 | ); |
b99299ba |
190 | my $short_class = $plugin_config->{'class'} ? |
191 | delete $plugin_config->{'class'} |
192 | : $plugin; |
193 | my $class = $short_class =~ /::/ ? |
194 | $short_class |
195 | : __PACKAGE__ . '::' . $short_class; |
f81dfa28 |
196 | |
956a83d8 |
197 | Class::MOP::load_class($class); |
be2a019a |
198 | |
b99299ba |
199 | return $cache->{$class} = $class->new($plugin_config); |
be2a019a |
200 | } |
201 | |
ada1ae3c |
202 | =head1 SEE ALSO |
203 | |
f81dfa28 |
204 | L<Catalyst::Plugin::SubRequest|Catalyst::Plugin::SubRequest>, |
4e327756 |
205 | L<Moose::Role|Moose::Role>, L<Moose|Moose>, |
ada1ae3c |
206 | L<http://www.catalystframework.org/calendar/2008/17> |
207 | |
208 | =head1 BUGS |
209 | |
210 | Please report any bugs or feature requests to |
211 | C<bug-catalyst-view-component-subinclude at rt.cpan.org>, or through the web interface at |
212 | L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Catalyst-View-Component-SubInclude>. |
213 | I will be notified, and then you'll automatically be notified of progress on |
214 | your bug as I make changes. |
215 | |
216 | =head1 AUTHOR |
217 | |
218 | Nilson Santos Figueiredo Junior, C<< <nilsonsfj at cpan.org> >> |
219 | |
976b0551 |
220 | =head1 CONTRIBUTORS |
221 | |
222 | Tomas Doran (t0m) C<< <bobtfish@bobtfish.net >>. |
223 | |
4b86766c |
224 | Vladimir Timofeev, C<< <vovkasm at gmail.com> >>. |
225 | |
c61362ea |
226 | Wallace Reis (wreis) C<< <wreis@cpan.org> >>. |
227 | |
ada1ae3c |
228 | =head1 SPONSORSHIP |
229 | |
230 | Development sponsored by Ionzero LLC L<http://www.ionzero.com/>. |
231 | |
232 | =head1 COPYRIGHT & LICENSE |
233 | |
976b0551 |
234 | Copyright (C) 2010 Nilson Santos Figueiredo Junior and the above contributors. |
235 | |
ada1ae3c |
236 | Copyright (C) 2009 Nilson Santos Figueiredo Junior. |
237 | |
238 | Copyright (C) 2009 Ionzero LLC. |
239 | |
240 | This program is free software; you can redistribute it and/or modify it |
241 | under the same terms as Perl itself. |
242 | |
243 | =cut |
244 | |
30726632 |
245 | 1; |