Document the keep_stash option for each plugin
[catagits/Catalyst-View-Component-SubInclude.git] / lib / Catalyst / View / Component / SubInclude.pm
CommitLineData
30726632 1package Catalyst::View::Component::SubInclude;
2use Moose::Role;
3
4use Carp qw/croak/;
7094e990 5use Catalyst::Utils ();
956a83d8 6use Class::MOP ();
7use MooseX::Types::Moose qw/Str HashRef/;
f91a7d21 8use namespace::clean -except => 'meta';
30726632 9
d547aa95 10with 'Catalyst::Component::ContextClosure';
11
ada1ae3c 12=head1 NAME
13
14Catalyst::View::Component::SubInclude - Use subincludes in your Catalyst views
15
16=head1 VERSION
17
e02835f5 18Version 0.11
ada1ae3c 19
20=cut
21
e02835f5 22our $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
35Then, somewhere in your templates:
36
37 [% subinclude('/my/widget') %]
be2a019a 38 [% subinclude_using('SubRequest', '/page/footer') %]
ada1ae3c 39
40=head1 DESCRIPTION
41
42C<Catalyst::View::Component::SubInclude> allows you to include content in your
43templates (or, more generally, somewhere in your view's C<render> processing)
f81dfa28 44which comes from another action in your application. It's implemented as a
4e327756 45L<Moose::Role|Moose::Role>, so using L<Moose|Moose> in your view is required.
ada1ae3c 46
47Simply put, it's a way to include the output of a Catalyst sub-request somewhere
f81dfa28 48in your page.
ada1ae3c 49
6bd0988d 50It's built in an extensible way so that you're free to use sub-requests,
51Varnish ESI (L<http://www.catalystframework.org/calendar/2008/17>) or any other
1152381d 52sub-include plugin you might want to implement.
ada1ae3c 53
be2a019a 54=head1 STASH FUNCTIONS
ada1ae3c 55
56This component does its magic by exporting a C<subinclude> coderef entry to the
f81dfa28 57stash. This way, it's easily accessible by the templates (which is the most
ada1ae3c 58common use-case).
59
60=head2 C<subinclude( $path, @args )>
61
f81dfa28 62This will render and return the body of the included resource (as specified by
be2a019a 63C<$path>) using the default subinclude plugin.
64
65=head2 C<subinclude_using( $plugin, $path, @args )>
66
f81dfa28 67This will render and return the body of the included resource (as specified by
be2a019a 68C<$path>) using the specified subinclude plugin.
69
f81dfa28 70The C<subinclude> function above is implemented basically as a shortcut which
be2a019a 71calls this function using the default plugin as the first parameter.
ada1ae3c 72
73=head1 SUBINCLUDE PLUGINS
74
f81dfa28 75The module comes with two subinclude plugins:
e88af283 76L<SubRequest|Catalyst::Plugin::View::Component::SubRequest>,
f81dfa28 77L<Visit|Catalyst::Plugin::View::Component::Visit> and
ada1ae3c 78L<ESI|Catalyst::Plugin::View::Component::ESI>.
79
f81dfa28 80By default, the C<SubRequest> plugin will be used. This can be changed in the
ada1ae3c 81view's configuration options (either in the config file or in the view module
f81dfa28 82itself).
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
101You can change each plugins' configuration through the keys in the 'subinclude'
102config key (example above)
ada1ae3c 103
be2a019a 104=head2 C<set_subinclude_plugin( $plugin )>
105
106This method changes the current active subinclude plugin in runtime. It expects
f81dfa28 107the plugin suffix (e.g. C<ESI> or C<SubRequest>) or a fully-qualified class
be2a019a 108name in the C<Catalyst::View::Component::SubInclude> namespace.
109
110=head2 Writing plugins
111
f81dfa28 112If writing your own plugin, keep in kind plugins are required to implement a
11a93ea1 113class method C<generate_subinclude> with the following signature:
114
115 sub generate_subinclude {
116 my ($class, $c, @args) = @_;
117 }
118
be2a019a 119The default plugin is stored in the C<subinclude_plugin> which can be changed
120in runtime. It expects a fully qualified class name.
121
ada1ae3c 122=cut
123
30726632 124has 'subinclude_plugin' => (
125 is => 'rw',
956a83d8 126 isa => Str,
be2a019a 127);
30726632 128
35ebe0b6 129has subinclude => (
130 is => 'ro',
131 isa => HashRef,
132 default => sub { {} },
133);
134
30726632 135around '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 147before '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 154sub 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
161sub _subinclude {
162 my ($self, $c, @args) = @_;
163 $self->_subinclude_using( $c, $self->subinclude_plugin, @args );
164}
165
166sub _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 172has _subinclude_plugin_class_instance_cache => (
173 isa => HashRef,
174 is => 'ro',
175 default => sub { {} },
176);
177
178sub _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 202L<Catalyst::Plugin::SubRequest|Catalyst::Plugin::SubRequest>,
4e327756 203L<Moose::Role|Moose::Role>, L<Moose|Moose>,
ada1ae3c 204L<http://www.catalystframework.org/calendar/2008/17>
205
206=head1 BUGS
207
208Please report any bugs or feature requests to
209C<bug-catalyst-view-component-subinclude at rt.cpan.org>, or through the web interface at
210L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Catalyst-View-Component-SubInclude>.
211I will be notified, and then you'll automatically be notified of progress on
212your bug as I make changes.
213
214=head1 AUTHOR
215
216Nilson Santos Figueiredo Junior, C<< <nilsonsfj at cpan.org> >>
217
976b0551 218=head1 CONTRIBUTORS
219
220Tomas Doran (t0m) C<< <bobtfish@bobtfish.net >>.
221
4b86766c 222Vladimir Timofeev, C<< <vovkasm at gmail.com> >>.
223
c61362ea 224Wallace Reis (wreis) C<< <wreis@cpan.org> >>.
225
ada1ae3c 226=head1 SPONSORSHIP
227
228Development sponsored by Ionzero LLC L<http://www.ionzero.com/>.
229
230=head1 COPYRIGHT & LICENSE
231
976b0551 232Copyright (C) 2010 Nilson Santos Figueiredo Junior and the above contributors.
233
ada1ae3c 234Copyright (C) 2009 Nilson Santos Figueiredo Junior.
235
236Copyright (C) 2009 Ionzero LLC.
237
238This program is free software; you can redistribute it and/or modify it
239under the same terms as Perl itself.
240
241=cut
242
30726632 2431;