e4505e064b1e91c625aa61b732e86060578c8c82
[catagits/Catalyst-View-Component-SubInclude.git] / lib / Catalyst / View / Component / SubInclude.pm
1 package Catalyst::View::Component::SubInclude;
2 use Moose::Role;
3
4 use Carp qw/croak/;
5 use namespace::clean qw/croak/;
6
7 =head1 NAME
8
9 Catalyst::View::Component::SubInclude - Use subincludes in your Catalyst views
10
11 =head1 VERSION
12
13 Version 0.05
14
15 =cut
16
17 our $VERSION = '0.05';
18
19 =head1 SYNOPSIS
20
21   package MyApp::View::TT;
22   use Moose;
23
24   extends 'Catalyst::View::TT';
25   with 'Catalyst::View::Component::SubInclude';
26
27   __PACKAGE__->config( subinclude_plugin => 'SubRequest' );
28
29 Then, somewhere in your templates:
30
31   [% subinclude('/my/widget') %]
32   [% subinclude_using('SubRequest', '/page/footer') %]
33
34 =head1 DESCRIPTION
35
36 C<Catalyst::View::Component::SubInclude> allows you to include content in your
37 templates (or, more generally, somewhere in your view's C<render> processing)
38 which comes from another action in your application. It's implemented as a 
39 L<Moose::Role|Moose::Role>, so using L<Moose|Moose> in your view is required.
40
41 Simply put, it's a way to include the output of a Catalyst sub-request somewhere
42 in your page. 
43
44 It's built in an extensible way so that you're free to use sub-requests, Varnish 
45 ESI (L<http://www.catalystframework.org/calendar/2008/17>) or any other 
46 sub-include plugin you might want to implement. An LWP plugin seems useful and
47 might be developed in the future.
48
49 =head1 STASH FUNCTIONS
50
51 This component does its magic by exporting a C<subinclude> coderef entry to the
52 stash. This way, it's easily accessible by the templates (which is the most 
53 common use-case).
54
55 =head2 C<subinclude( $path, @args )>
56
57 This will render and return the body of the included resource (as specified by 
58 C<$path>) using the default subinclude plugin.
59
60 =head2 C<subinclude_using( $plugin, $path, @args )>
61
62 This will render and return the body of the included resource (as specified by 
63 C<$path>) using the specified subinclude plugin.
64
65 The C<subinclude> function above is implemented basically as a shortcut which 
66 calls this function using the default plugin as the first parameter.
67
68 =head1 SUBINCLUDE PLUGINS
69
70 The module comes with two subinclude plugins: 
71 L<SubRequest|Catalyst::Plugin::View::Component::SubRequest>,
72 L<Visit|Catalyst::Plugin::View::Component::Visit> and 
73 L<ESI|Catalyst::Plugin::View::Component::ESI>.
74
75 By default, the C<SubRequest> plugin will be used. This can be changed in the 
76 view's configuration options (either in the config file or in the view module
77 itself). 
78
79 Configuration file example:
80
81   <View::TT>
82       subinclude_plugin   ESI
83   </View::TT>
84
85 =head2 C<set_subinclude_plugin( $plugin )>
86
87 This method changes the current active subinclude plugin in runtime. It expects
88 the plugin suffix (e.g. C<ESI> or C<SubRequest>) or a fully-qualified class 
89 name in the C<Catalyst::View::Component::SubInclude> namespace.
90
91 =head2 Writing plugins
92
93 If writing your own plugin, keep in kind plugins are required to implement a 
94 class method C<generate_subinclude> with the following signature:
95
96   sub generate_subinclude {
97       my ($class, $c, @args) = @_;
98   }
99
100 The default plugin is stored in the C<subinclude_plugin> which can be changed
101 in runtime. It expects a fully qualified class name.
102
103 =cut
104
105 has 'subinclude_plugin' => (
106     is => 'rw',
107     isa => 'Str'
108 );
109
110 around 'new' => sub {
111     my $next = shift;
112     my $class = shift;
113     
114     my $self = $class->$next( @_ );
115     
116     my $subinclude_plugin = $self->config->{subinclude_plugin} || 'SubRequest';
117     $self->set_subinclude_plugin( $subinclude_plugin );
118     
119     $self;
120 };
121
122 around 'render' => sub {
123     my $next = shift;
124     my ($self, $c, @args) = @_;
125     
126     $c->stash->{subinclude}       = sub { $self->_subinclude( $c, @_ ) };
127     $c->stash->{subinclude_using} = sub { $self->_subinclude_using( $c, @_ ) };
128
129     $self->$next( $c, @args );
130 };
131
132 sub set_subinclude_plugin {
133     my ($self, $plugin) = @_;
134
135     my $subinclude_class = $self->_subinclude_plugin_class_name( $plugin );
136     $self->subinclude_plugin( $subinclude_class );
137 }
138
139 sub _subinclude {
140     my ($self, $c, @args) = @_;
141     $self->_subinclude_using( $c, $self->subinclude_plugin, @args );
142 }
143
144 sub _subinclude_using {
145     my ($self, $c, $plugin, @args) = @_;
146     $plugin = $self->_subinclude_plugin_class_name($plugin);
147     $plugin->generate_subinclude( $c, @args );
148 }
149
150 sub _subinclude_plugin_class_name {
151     my ($self, $plugin) = @_;
152     
153     # check if name is already fully qualified
154     my $pkg = __PACKAGE__;
155     return $plugin if $plugin =~ /^$pkg/;
156
157     my $class_name = __PACKAGE__ . '::' . $plugin;
158     
159     eval "require $class_name";
160     croak "Error requiring $class_name: $@" if $@;
161
162     $class_name;
163 }
164
165 =head1 SEE ALSO
166
167 L<Catalyst::Plugin::SubRequest|Catalyst::Plugin::SubRequest>, 
168 L<Moose::Role|Moose::Role>, L<Moose|Moose>,
169 L<http://www.catalystframework.org/calendar/2008/17>
170
171 =head1 BUGS
172
173 Please report any bugs or feature requests to
174 C<bug-catalyst-view-component-subinclude at rt.cpan.org>, or through the web interface at
175 L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Catalyst-View-Component-SubInclude>.
176 I will be notified, and then you'll automatically be notified of progress on
177 your bug as I make changes.
178
179 =head1 AUTHOR
180
181 Nilson Santos Figueiredo Junior, C<< <nilsonsfj at cpan.org> >>
182
183 =head1 SPONSORSHIP
184
185 Development sponsored by Ionzero LLC L<http://www.ionzero.com/>.
186
187 =head1 COPYRIGHT & LICENSE
188
189 Copyright (C) 2009 Nilson Santos Figueiredo Junior.
190
191 Copyright (C) 2009 Ionzero LLC.
192
193 This program is free software; you can redistribute it and/or modify it
194 under the same terms as Perl itself.
195
196 =cut
197
198 1;