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 | |
f81dfa28 |
75 | The module comes with two subinclude plugins: |
e88af283 |
76 | L<SubRequest|Catalyst::Plugin::View::Component::SubRequest>, |
f81dfa28 |
77 | L<Visit|Catalyst::Plugin::View::Component::Visit> and |
ada1ae3c |
78 | L<ESI|Catalyst::Plugin::View::Component::ESI>. |
79 | |
f81dfa28 |
80 | By default, the C<SubRequest> plugin will be used. This can be changed in the |
ada1ae3c |
81 | view's configuration options (either in the config file or in the view module |
f81dfa28 |
82 | itself). |
ada1ae3c |
83 | |
4162256a |
84 | __PACKAGE__->config( |
85 | subinclude_plugin => 'ESI', |
86 | subinclude => { |
87 | 'SubRequest' => { |
88 | keep_stash => 1, |
89 | }, |
90 | 'HTTP::POST' => { |
91 | class => 'HTTP', |
92 | http_method => 'POST', |
93 | ua_timeout => '10', |
94 | uri_map => { |
95 | '/foo/' => 'http://www.foo.com/', |
96 | }, |
97 | }, |
98 | }, |
99 | ); |
100 | |
101 | You can change each plugins' configuration through the keys in the 'subinclude' |
102 | config key (example above) |
ada1ae3c |
103 | |
be2a019a |
104 | =head2 C<set_subinclude_plugin( $plugin )> |
105 | |
106 | This method changes the current active subinclude plugin in runtime. It expects |
f81dfa28 |
107 | the plugin suffix (e.g. C<ESI> or C<SubRequest>) or a fully-qualified class |
be2a019a |
108 | name in the C<Catalyst::View::Component::SubInclude> namespace. |
109 | |
110 | =head2 Writing plugins |
111 | |
f81dfa28 |
112 | If writing your own plugin, keep in kind plugins are required to implement a |
11a93ea1 |
113 | class method C<generate_subinclude> with the following signature: |
114 | |
115 | sub generate_subinclude { |
116 | my ($class, $c, @args) = @_; |
117 | } |
118 | |
be2a019a |
119 | The default plugin is stored in the C<subinclude_plugin> which can be changed |
120 | in runtime. It expects a fully qualified class name. |
121 | |
ada1ae3c |
122 | =cut |
123 | |
30726632 |
124 | has 'subinclude_plugin' => ( |
125 | is => 'rw', |
956a83d8 |
126 | isa => Str, |
be2a019a |
127 | ); |
30726632 |
128 | |
35ebe0b6 |
129 | has subinclude => ( |
130 | is => 'ro', |
131 | isa => HashRef, |
132 | default => sub { {} }, |
133 | ); |
134 | |
30726632 |
135 | around 'new' => sub { |
136 | my $next = shift; |
137 | my $class = shift; |
f81dfa28 |
138 | |
30726632 |
139 | my $self = $class->$next( @_ ); |
f81dfa28 |
140 | |
30726632 |
141 | my $subinclude_plugin = $self->config->{subinclude_plugin} || 'SubRequest'; |
be2a019a |
142 | $self->set_subinclude_plugin( $subinclude_plugin ); |
f81dfa28 |
143 | |
30726632 |
144 | $self; |
145 | }; |
146 | |
1869d781 |
147 | before 'render' => sub { |
30726632 |
148 | my ($self, $c, @args) = @_; |
ab0b6bbd |
149 | |
d547aa95 |
150 | $c->stash->{subinclude} = $self->make_context_closure(sub { $self->_subinclude( @_ ) }, $c); |
151 | $c->stash->{subinclude_using} = $self->make_context_closure(sub { $self->_subinclude_using( @_ ) }, $c); |
30726632 |
152 | }; |
153 | |
be2a019a |
154 | sub set_subinclude_plugin { |
155 | my ($self, $plugin) = @_; |
156 | |
956a83d8 |
157 | my $subinclude_class = blessed $self->_subinclude_plugin_class_instance( $plugin ); |
be2a019a |
158 | $self->subinclude_plugin( $subinclude_class ); |
159 | } |
160 | |
161 | sub _subinclude { |
162 | my ($self, $c, @args) = @_; |
163 | $self->_subinclude_using( $c, $self->subinclude_plugin, @args ); |
164 | } |
165 | |
166 | sub _subinclude_using { |
167 | my ($self, $c, $plugin, @args) = @_; |
956a83d8 |
168 | $plugin = $self->_subinclude_plugin_class_instance($plugin); |
169 | $plugin->generate_subinclude( $c, @args ); |
be2a019a |
170 | } |
171 | |
956a83d8 |
172 | has _subinclude_plugin_class_instance_cache => ( |
173 | isa => HashRef, |
174 | is => 'ro', |
175 | default => sub { {} }, |
176 | ); |
177 | |
178 | sub _subinclude_plugin_class_instance { |
be2a019a |
179 | my ($self, $plugin) = @_; |
f81dfa28 |
180 | |
956a83d8 |
181 | my $cache = $self->_subinclude_plugin_class_instance_cache; |
182 | return $cache->{$plugin} if exists $cache->{$plugin}; |
be2a019a |
183 | |
956a83d8 |
184 | my $plugin_config = Catalyst::Utils::merge_hashes( |
35ebe0b6 |
185 | $self->subinclude->{ALL}||{}, |
186 | $self->subinclude->{$plugin}||{} |
956a83d8 |
187 | ); |
b99299ba |
188 | my $short_class = $plugin_config->{'class'} ? |
189 | delete $plugin_config->{'class'} |
190 | : $plugin; |
191 | my $class = $short_class =~ /::/ ? |
192 | $short_class |
193 | : __PACKAGE__ . '::' . $short_class; |
f81dfa28 |
194 | |
956a83d8 |
195 | Class::MOP::load_class($class); |
be2a019a |
196 | |
b99299ba |
197 | return $cache->{$class} = $class->new($plugin_config); |
be2a019a |
198 | } |
199 | |
ada1ae3c |
200 | =head1 SEE ALSO |
201 | |
f81dfa28 |
202 | L<Catalyst::Plugin::SubRequest|Catalyst::Plugin::SubRequest>, |
4e327756 |
203 | L<Moose::Role|Moose::Role>, L<Moose|Moose>, |
ada1ae3c |
204 | L<http://www.catalystframework.org/calendar/2008/17> |
205 | |
206 | =head1 BUGS |
207 | |
208 | Please report any bugs or feature requests to |
209 | C<bug-catalyst-view-component-subinclude at rt.cpan.org>, or through the web interface at |
210 | L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Catalyst-View-Component-SubInclude>. |
211 | I will be notified, and then you'll automatically be notified of progress on |
212 | your bug as I make changes. |
213 | |
214 | =head1 AUTHOR |
215 | |
216 | Nilson Santos Figueiredo Junior, C<< <nilsonsfj at cpan.org> >> |
217 | |
976b0551 |
218 | =head1 CONTRIBUTORS |
219 | |
220 | Tomas Doran (t0m) C<< <bobtfish@bobtfish.net >>. |
221 | |
4b86766c |
222 | Vladimir Timofeev, C<< <vovkasm at gmail.com> >>. |
223 | |
c61362ea |
224 | Wallace Reis (wreis) C<< <wreis@cpan.org> >>. |
225 | |
ada1ae3c |
226 | =head1 SPONSORSHIP |
227 | |
228 | Development sponsored by Ionzero LLC L<http://www.ionzero.com/>. |
229 | |
230 | =head1 COPYRIGHT & LICENSE |
231 | |
976b0551 |
232 | Copyright (C) 2010 Nilson Santos Figueiredo Junior and the above contributors. |
233 | |
ada1ae3c |
234 | Copyright (C) 2009 Nilson Santos Figueiredo Junior. |
235 | |
236 | Copyright (C) 2009 Ionzero LLC. |
237 | |
238 | This program is free software; you can redistribute it and/or modify it |
239 | under the same terms as Perl itself. |
240 | |
241 | =cut |
242 | |
30726632 |
243 | 1; |