Version 0.09
[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
dcdc4ec8 18Version 0.09
ada1ae3c 19
20=cut
21
dcdc4ec8 22our $VERSION = '0.09';
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
ada1ae3c 52sub-include plugin you might want to implement. An LWP plugin seems useful and
6bd0988d 53might be developed in the future. If you need to address a resource by it's
54public path (i.e. the path part trailing C<http://example.com/myapp> then you
55will need to use L<Catalyst::Plugin::SubRequest> directly, and not this
56component.
ada1ae3c 57
be2a019a 58=head1 STASH FUNCTIONS
ada1ae3c 59
60This component does its magic by exporting a C<subinclude> coderef entry to the
f81dfa28 61stash. This way, it's easily accessible by the templates (which is the most
ada1ae3c 62common use-case).
63
64=head2 C<subinclude( $path, @args )>
65
f81dfa28 66This will render and return the body of the included resource (as specified by
be2a019a 67C<$path>) using the default subinclude plugin.
68
69=head2 C<subinclude_using( $plugin, $path, @args )>
70
f81dfa28 71This will render and return the body of the included resource (as specified by
be2a019a 72C<$path>) using the specified subinclude plugin.
73
f81dfa28 74The C<subinclude> function above is implemented basically as a shortcut which
be2a019a 75calls this function using the default plugin as the first parameter.
ada1ae3c 76
77=head1 SUBINCLUDE PLUGINS
78
f81dfa28 79The module comes with two subinclude plugins:
e88af283 80L<SubRequest|Catalyst::Plugin::View::Component::SubRequest>,
f81dfa28 81L<Visit|Catalyst::Plugin::View::Component::Visit> and
ada1ae3c 82L<ESI|Catalyst::Plugin::View::Component::ESI>.
83
f81dfa28 84By default, the C<SubRequest> plugin will be used. This can be changed in the
ada1ae3c 85view's configuration options (either in the config file or in the view module
f81dfa28 86itself).
ada1ae3c 87
88Configuration file example:
89
90 <View::TT>
91 subinclude_plugin ESI
92 </View::TT>
93
be2a019a 94=head2 C<set_subinclude_plugin( $plugin )>
95
96This method changes the current active subinclude plugin in runtime. It expects
f81dfa28 97the plugin suffix (e.g. C<ESI> or C<SubRequest>) or a fully-qualified class
be2a019a 98name in the C<Catalyst::View::Component::SubInclude> namespace.
99
100=head2 Writing plugins
101
f81dfa28 102If writing your own plugin, keep in kind plugins are required to implement a
11a93ea1 103class method C<generate_subinclude> with the following signature:
104
105 sub generate_subinclude {
106 my ($class, $c, @args) = @_;
107 }
108
be2a019a 109The default plugin is stored in the C<subinclude_plugin> which can be changed
110in runtime. It expects a fully qualified class name.
111
ada1ae3c 112=cut
113
30726632 114has 'subinclude_plugin' => (
115 is => 'rw',
956a83d8 116 isa => Str,
be2a019a 117);
30726632 118
119around 'new' => sub {
120 my $next = shift;
121 my $class = shift;
f81dfa28 122
30726632 123 my $self = $class->$next( @_ );
f81dfa28 124
30726632 125 my $subinclude_plugin = $self->config->{subinclude_plugin} || 'SubRequest';
be2a019a 126 $self->set_subinclude_plugin( $subinclude_plugin );
f81dfa28 127
30726632 128 $self;
129};
130
1869d781 131before 'render' => sub {
30726632 132 my ($self, $c, @args) = @_;
ab0b6bbd 133
d547aa95 134 $c->stash->{subinclude} = $self->make_context_closure(sub { $self->_subinclude( @_ ) }, $c);
135 $c->stash->{subinclude_using} = $self->make_context_closure(sub { $self->_subinclude_using( @_ ) }, $c);
30726632 136};
137
be2a019a 138sub set_subinclude_plugin {
139 my ($self, $plugin) = @_;
140
956a83d8 141 my $subinclude_class = blessed $self->_subinclude_plugin_class_instance( $plugin );
be2a019a 142 $self->subinclude_plugin( $subinclude_class );
143}
144
145sub _subinclude {
146 my ($self, $c, @args) = @_;
147 $self->_subinclude_using( $c, $self->subinclude_plugin, @args );
148}
149
150sub _subinclude_using {
151 my ($self, $c, $plugin, @args) = @_;
956a83d8 152 $plugin = $self->_subinclude_plugin_class_instance($plugin);
153 $plugin->generate_subinclude( $c, @args );
be2a019a 154}
155
956a83d8 156has _subinclude_plugin_class_instance_cache => (
157 isa => HashRef,
158 is => 'ro',
159 default => sub { {} },
160);
161
162sub _subinclude_plugin_class_instance {
be2a019a 163 my ($self, $plugin) = @_;
f81dfa28 164
956a83d8 165 my $class = $plugin =~ /::/ ? $plugin : __PACKAGE__ . '::' . $plugin;
166
167 my $cache = $self->_subinclude_plugin_class_instance_cache;
168 return $cache->{$plugin} if exists $cache->{$plugin};
be2a019a 169
956a83d8 170 my $plugin_config = Catalyst::Utils::merge_hashes(
171 $self->config->{subinclude}->{ALL}||{},
172 $self->config->{subinclude}->{$plugin}||{}
173 );
f81dfa28 174
956a83d8 175 Class::MOP::load_class($class);
be2a019a 176
956a83d8 177 return $cache->{$plugin} = $class->new($plugin_config);
be2a019a 178}
179
ada1ae3c 180=head1 SEE ALSO
181
f81dfa28 182L<Catalyst::Plugin::SubRequest|Catalyst::Plugin::SubRequest>,
4e327756 183L<Moose::Role|Moose::Role>, L<Moose|Moose>,
ada1ae3c 184L<http://www.catalystframework.org/calendar/2008/17>
185
186=head1 BUGS
187
188Please report any bugs or feature requests to
189C<bug-catalyst-view-component-subinclude at rt.cpan.org>, or through the web interface at
190L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Catalyst-View-Component-SubInclude>.
191I will be notified, and then you'll automatically be notified of progress on
192your bug as I make changes.
193
194=head1 AUTHOR
195
196Nilson Santos Figueiredo Junior, C<< <nilsonsfj at cpan.org> >>
197
976b0551 198=head1 CONTRIBUTORS
199
200Tomas Doran (t0m) C<< <bobtfish@bobtfish.net >>.
201
ada1ae3c 202=head1 SPONSORSHIP
203
204Development sponsored by Ionzero LLC L<http://www.ionzero.com/>.
205
206=head1 COPYRIGHT & LICENSE
207
976b0551 208Copyright (C) 2010 Nilson Santos Figueiredo Junior and the above contributors.
209
ada1ae3c 210Copyright (C) 2009 Nilson Santos Figueiredo Junior.
211
212Copyright (C) 2009 Ionzero LLC.
213
214This program is free software; you can redistribute it and/or modify it
215under the same terms as Perl itself.
216
217=cut
218
30726632 2191;