use Carp qw/croak/;
use Catalyst::Utils ();
+use Class::MOP ();
+use MooseX::Types::Moose qw/Str HashRef/;
use namespace::clean -except => 'meta';
with 'Catalyst::Component::ContextClosure';
=head1 VERSION
-Version 0.07
+Version 0.08
=cut
-our $VERSION = '0.07';
+our $VERSION = '0.08';
+$VERSION = eval $VERSION;
=head1 SYNOPSIS
C<Catalyst::View::Component::SubInclude> allows you to include content in your
templates (or, more generally, somewhere in your view's C<render> processing)
-which comes from another action in your application. It's implemented as a
+which comes from another action in your application. It's implemented as a
L<Moose::Role|Moose::Role>, so using L<Moose|Moose> in your view is required.
Simply put, it's a way to include the output of a Catalyst sub-request somewhere
-in your page.
+in your page.
-It's built in an extensible way so that you're free to use sub-requests, Varnish
-ESI (L<http://www.catalystframework.org/calendar/2008/17>) or any other
+It's built in an extensible way so that you're free to use sub-requests,
+Varnish ESI (L<http://www.catalystframework.org/calendar/2008/17>) or any other
sub-include plugin you might want to implement. An LWP plugin seems useful and
-might be developed in the future.
+might be developed in the future. If you need to address a resource by it's
+public path (i.e. the path part trailing C<http://example.com/myapp> then you
+will need to use L<Catalyst::Plugin::SubRequest> directly, and not this
+component.
=head1 STASH FUNCTIONS
This component does its magic by exporting a C<subinclude> coderef entry to the
-stash. This way, it's easily accessible by the templates (which is the most
+stash. This way, it's easily accessible by the templates (which is the most
common use-case).
=head2 C<subinclude( $path, @args )>
-This will render and return the body of the included resource (as specified by
+This will render and return the body of the included resource (as specified by
C<$path>) using the default subinclude plugin.
=head2 C<subinclude_using( $plugin, $path, @args )>
-This will render and return the body of the included resource (as specified by
+This will render and return the body of the included resource (as specified by
C<$path>) using the specified subinclude plugin.
-The C<subinclude> function above is implemented basically as a shortcut which
+The C<subinclude> function above is implemented basically as a shortcut which
calls this function using the default plugin as the first parameter.
=head1 SUBINCLUDE PLUGINS
-The module comes with two subinclude plugins:
+The module comes with two subinclude plugins:
L<SubRequest|Catalyst::Plugin::View::Component::SubRequest>,
-L<Visit|Catalyst::Plugin::View::Component::Visit> and
+L<Visit|Catalyst::Plugin::View::Component::Visit> and
L<ESI|Catalyst::Plugin::View::Component::ESI>.
-By default, the C<SubRequest> plugin will be used. This can be changed in the
+By default, the C<SubRequest> plugin will be used. This can be changed in the
view's configuration options (either in the config file or in the view module
-itself).
+itself).
Configuration file example:
=head2 C<set_subinclude_plugin( $plugin )>
This method changes the current active subinclude plugin in runtime. It expects
-the plugin suffix (e.g. C<ESI> or C<SubRequest>) or a fully-qualified class
+the plugin suffix (e.g. C<ESI> or C<SubRequest>) or a fully-qualified class
name in the C<Catalyst::View::Component::SubInclude> namespace.
=head2 Writing plugins
-If writing your own plugin, keep in kind plugins are required to implement a
+If writing your own plugin, keep in kind plugins are required to implement a
class method C<generate_subinclude> with the following signature:
sub generate_subinclude {
has 'subinclude_plugin' => (
is => 'rw',
- isa => 'Str'
+ isa => Str,
);
around 'new' => sub {
my $next = shift;
my $class = shift;
-
+
my $self = $class->$next( @_ );
-
+
my $subinclude_plugin = $self->config->{subinclude_plugin} || 'SubRequest';
$self->set_subinclude_plugin( $subinclude_plugin );
-
+
$self;
};
sub set_subinclude_plugin {
my ($self, $plugin) = @_;
- my $subinclude_class = $self->_subinclude_plugin_class_name( $plugin );
+ my $subinclude_class = blessed $self->_subinclude_plugin_class_instance( $plugin );
$self->subinclude_plugin( $subinclude_class );
}
sub _subinclude_using {
my ($self, $c, $plugin, @args) = @_;
- $plugin = $self->_subinclude_plugin_class_name($plugin);
- my $plugin_config = Catalyst::Utils::merge_hashes($self->config->{subinclude}->{ALL}||{}, $self->config->{subinclude}->{$plugin}||{});
- $plugin->new($plugin_config)->generate_subinclude( $c, @args );
+ $plugin = $self->_subinclude_plugin_class_instance($plugin);
+ $plugin->generate_subinclude( $c, @args );
}
-sub _subinclude_plugin_class_name {
+has _subinclude_plugin_class_instance_cache => (
+ isa => HashRef,
+ is => 'ro',
+ default => sub { {} },
+);
+
+sub _subinclude_plugin_class_instance {
my ($self, $plugin) = @_;
-
- # check if name is already fully qualified
- my $pkg = __PACKAGE__;
- return $plugin if $plugin =~ /^$pkg/;
- my $class_name = __PACKAGE__ . '::' . $plugin;
-
- eval "require $class_name";
- croak "Error requiring $class_name: $@" if $@;
+ my $class = $plugin =~ /::/ ? $plugin : __PACKAGE__ . '::' . $plugin;
+
+ my $cache = $self->_subinclude_plugin_class_instance_cache;
+ return $cache->{$plugin} if exists $cache->{$plugin};
- $class_name;
+ my $plugin_config = Catalyst::Utils::merge_hashes(
+ $self->config->{subinclude}->{ALL}||{},
+ $self->config->{subinclude}->{$plugin}||{}
+ );
+
+ Class::MOP::load_class($class);
+
+ return $cache->{$plugin} = $class->new($plugin_config);
}
=head1 SEE ALSO
-L<Catalyst::Plugin::SubRequest|Catalyst::Plugin::SubRequest>,
+L<Catalyst::Plugin::SubRequest|Catalyst::Plugin::SubRequest>,
L<Moose::Role|Moose::Role>, L<Moose|Moose>,
L<http://www.catalystframework.org/calendar/2008/17>
Nilson Santos Figueiredo Junior, C<< <nilsonsfj at cpan.org> >>
+=head1 CONTRIBUTORS
+
+Tomas Doran (t0m) C<< <bobtfish@bobtfish.net >>.
+
=head1 SPONSORSHIP
Development sponsored by Ionzero LLC L<http://www.ionzero.com/>.
=head1 COPYRIGHT & LICENSE
+Copyright (C) 2010 Nilson Santos Figueiredo Junior and the above contributors.
+
Copyright (C) 2009 Nilson Santos Figueiredo Junior.
Copyright (C) 2009 Ionzero LLC.