X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FCatalyst%2FView%2FComponent%2FSubInclude.pm;h=de3b20ac82553940a5131e42026a4fdd56628249;hb=956a83d8811378be1976e2e62a4fb8931535fefa;hp=db04ebb50f1af151a940f1c1ba279fad38a57c6f;hpb=ada1ae3c160cdae020acd8fa49a3913b8fb7f704;p=catagits%2FCatalyst-View-Component-SubInclude.git diff --git a/lib/Catalyst/View/Component/SubInclude.pm b/lib/Catalyst/View/Component/SubInclude.pm index db04ebb..de3b20a 100644 --- a/lib/Catalyst/View/Component/SubInclude.pm +++ b/lib/Catalyst/View/Component/SubInclude.pm @@ -2,7 +2,12 @@ package Catalyst::View::Component::SubInclude; use Moose::Role; use Carp qw/croak/; -use namespace::clean 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 NAME @@ -10,11 +15,11 @@ Catalyst::View::Component::SubInclude - Use subincludes in your Catalyst views =head1 VERSION -Version 0.01 +Version 0.07 =cut -our $VERSION = '0.01'; +our $VERSION = '0.07'; =head1 SYNOPSIS @@ -29,13 +34,14 @@ our $VERSION = '0.01'; Then, somewhere in your templates: [% subinclude('/my/widget') %] + [% subinclude_using('SubRequest', '/page/footer') %] =head1 DESCRIPTION C allows you to include content in your templates (or, more generally, somewhere in your view's C processing) which comes from another action in your application. It's implemented as a -L, so using L in your view is required. +L, so using L in your view is required. Simply put, it's a way to include the output of a Catalyst sub-request somewhere in your page. @@ -45,7 +51,7 @@ ESI (L) or any other sub-include plugin you might want to implement. An LWP plugin seems useful and might be developed in the future. -=head1 STASH FUNCTION +=head1 STASH FUNCTIONS This component does its magic by exporting a C coderef entry to the stash. This way, it's easily accessible by the templates (which is the most @@ -53,15 +59,25 @@ common use-case). =head2 C -This will return the body of the requested resource (as specified by C<$path>). +This will render and return the body of the included resource (as specified by +C<$path>) using the default subinclude plugin. + +=head2 C + +This will render and return the body of the included resource (as specified by +C<$path>) using the specified subinclude plugin. + +The C 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 and +L, +L and L. -By default, the SubRequest plugin will be used. This can be changed in the +By default, the C 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). @@ -71,12 +87,30 @@ Configuration file example: subinclude_plugin ESI +=head2 C + +This method changes the current active subinclude plugin in runtime. It expects +the plugin suffix (e.g. C or C) or a fully-qualified class +name in the C namespace. + +=head2 Writing plugins + +If writing your own plugin, keep in kind plugins are required to implement a +class method C with the following signature: + + sub generate_subinclude { + my ($class, $c, @args) = @_; + } + +The default plugin is stored in the C which can be changed +in runtime. It expects a fully qualified class name. + =cut has 'subinclude_plugin' => ( is => 'rw', - isa => 'ClassName' -); + isa => Str, +); around 'new' => sub { my $next = shift; @@ -85,30 +119,64 @@ around 'new' => sub { my $self = $class->$next( @_ ); my $subinclude_plugin = $self->config->{subinclude_plugin} || 'SubRequest'; - my $subinclude_class = __PACKAGE__ . '::' . $subinclude_plugin; - - eval "require $subinclude_class"; - croak "Error requiring $subinclude_class: $@" if $@; - - $self->subinclude_plugin( $subinclude_class ); + $self->set_subinclude_plugin( $subinclude_plugin ); $self; }; -around 'render' => sub { - my $next = shift; +before 'render' => sub { my ($self, $c, @args) = @_; - - $c->stash->{subinclude} = sub { - $self->subinclude_plugin->generate_subinclude( $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 = blessed $self->_subinclude_plugin_class_instance( $plugin ); + $self->subinclude_plugin( $subinclude_class ); +} + +sub _subinclude { + my ($self, $c, @args) = @_; + $self->_subinclude_using( $c, $self->subinclude_plugin, @args ); +} + +sub _subinclude_using { + my ($self, $c, $plugin, @args) = @_; + $plugin = $self->_subinclude_plugin_class_instance($plugin); + $plugin->generate_subinclude( $c, @args ); +} + +has _subinclude_plugin_class_instance_cache => ( + isa => HashRef, + is => 'ro', + default => sub { {} }, +); + +sub _subinclude_plugin_class_instance { + my ($self, $plugin) = @_; + + my $class = $plugin =~ /::/ ? $plugin : __PACKAGE__ . '::' . $plugin; + + my $cache = $self->_subinclude_plugin_class_instance_cache; + return $cache->{$plugin} if exists $cache->{$plugin}; + + 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, L, L, +L, +L, L, L =head1 BUGS