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