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