Fix plugin links in POD
[catagits/Catalyst-View-Component-SubInclude.git] / lib / Catalyst / View / Component / SubInclude.pm
index 50dd2c1..f77345f 100644 (file)
@@ -2,8 +2,12 @@ package Catalyst::View::Component::SubInclude;
 use Moose::Role;
 
 use Carp qw/croak/;
-use namespace::clean qw/croak/;
-use Scalar::Util qw/weaken/;
+use Catalyst::Utils ();
+use Class::MOP ();
+use MooseX::Types::Moose qw/Str HashRef/;
+use namespace::clean -except => 'meta';
+
+with 'Catalyst::Component::ContextClosure';
 
 =head1 NAME
 
@@ -11,11 +15,12 @@ Catalyst::View::Component::SubInclude - Use subincludes in your Catalyst views
 
 =head1 VERSION
 
-Version 0.05
+Version 0.11
 
 =cut
 
-our $VERSION = '0.06';
+our $VERSION = '0.11';
+$VERSION = eval $VERSION;
 
 =head1 SYNOPSIS
 
@@ -36,62 +41,77 @@ Then, somewhere in your templates:
 
 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 
-sub-include plugin you might want to implement. An LWP plugin seems useful and
-might be developed in the future.
+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.
 
 =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: 
-L<SubRequest|Catalyst::Plugin::View::Component::SubRequest>,
-L<Visit|Catalyst::Plugin::View::Component::Visit> and 
-L<ESI|Catalyst::Plugin::View::Component::ESI>.
+The module comes with several subinclude plugins:
+L<SubRequest|Catalyst::View::Component::SubInclude::SubRequest>,
+L<HTTP|Catalyst::View::Component::SubInclude::HTTP>,
+L<SSI|Catalyst::View::Component::SubInclude::SSI>,
+L<Visit|Catalyst::View::Component::SubInclude::Visit> and
+L<ESI|Catalyst::View::Component::SubInclude::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). 
-
-Configuration file example:
-
-  <View::TT>
-      subinclude_plugin   ESI
-  </View::TT>
+itself).
+
+    __PACKAGE__->config(
+        subinclude_plugin => 'ESI',
+        subinclude => {
+            'SubRequest' => {
+                keep_stash => 1,
+            },
+            'HTTP::POST' => {
+                class => 'HTTP',
+                http_method => 'POST',
+                ua_timeout => '10',
+                uri_map => {
+                    '/foo/' => 'http://www.foo.com/',
+                },
+            },
+        },
+    );
+
+You can change each plugins' configuration through the keys in the 'subinclude'
+config key (example above)
 
 =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 {
@@ -105,37 +125,38 @@ in runtime. It expects a fully qualified class name.
 
 has 'subinclude_plugin' => (
     is => 'rw',
-    isa => 'Str'
+    isa => Str,
+);
+
+has subinclude => (
+    is => 'ro',
+    isa => HashRef,
+    default => sub { {} },
 );
 
 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;
 };
 
-around 'render' => sub {
-    my $next = shift;
+before 'render' => sub {
     my ($self, $c, @args) = @_;
-   
-    weaken $c; 
-
-    $c->stash->{subinclude}       = sub { $self->_subinclude( $c, @_ ) };
-    $c->stash->{subinclude_using} = sub { $self->_subinclude_using( $c, @_ ) };
 
-    $self->$next( $c, @args );
+    $c->stash->{subinclude}       = $self->make_context_closure(sub { $self->_subinclude( @_ ) }, $c);
+    $c->stash->{subinclude_using} = $self->make_context_closure(sub { $self->_subinclude_using( @_ ) }, $c);
 };
 
 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 );
 }
 
@@ -146,28 +167,41 @@ sub _subinclude {
 
 sub _subinclude_using {
     my ($self, $c, $plugin, @args) = @_;
-    $plugin = $self->_subinclude_plugin_class_name($plugin);
+    $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 $cache = $self->_subinclude_plugin_class_instance_cache;
+    return $cache->{$plugin} if exists $cache->{$plugin};
+
+    my $plugin_config = Catalyst::Utils::merge_hashes(
+        $self->subinclude->{ALL}||{},
+        $self->subinclude->{$plugin}||{}
+    );
+    my $short_class = $plugin_config->{'class'} ?
+        delete $plugin_config->{'class'}
+        : $plugin;
+    my $class = $short_class =~ /::/ ?
+        $short_class
+        : __PACKAGE__ . '::' . $short_class;
 
-    $class_name;
+    Class::MOP::load_class($class);
+
+    return $cache->{$class} = $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>
 
@@ -183,12 +217,22 @@ your bug as I make changes.
 
 Nilson Santos Figueiredo Junior, C<< <nilsonsfj at cpan.org> >>
 
+=head1 CONTRIBUTORS
+
+Tomas Doran (t0m) C<< <bobtfish@bobtfish.net >>.
+
+Vladimir Timofeev, C<< <vovkasm at gmail.com> >>.
+
+Wallace Reis (wreis) C<< <wreis@cpan.org> >>.
+
 =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.