Now you can call $c->registered_plugins to find out which plugins are loaded.
Also, you can now use fully qualified plugin names when you load Catalyst:
use Catalyst qw(
DateTime
+Fully::Qualified::Plugin::Name
);
This makes it easy to add plugins which do not start with
"Catalyst::Plugin::".
use Catalyst qw/My::Module/;
+If your plugin starts with a name other than C<Catalyst::Plugin::>, you can
+fully qualify the name by using a unary plus:
+
+ use Catalyst qw/
+ My::Module
+ +Fully::Qualified::Plugin::Name
+ /;
+
Special flags like C<-Debug> and C<-Engine> can also be specified as
arguments when Catalyst is loaded:
sub plugin {
my ( $class, $name, $plugin, @args ) = @_;
- $plugin->require;
-
- if ( my $error = $UNIVERSAL::require::ERROR ) {
- Catalyst::Exception->throw(
- message => qq/Couldn't load instant plugin "$plugin", "$error"/ );
- }
+ $class->_register_plugin($plugin, 1);
eval { $plugin->import };
$class->mk_classdata($name);
=cut
-sub setup_plugins {
- my ( $class, $plugins ) = @_;
+=head2 $c->registered_plugins
+
+Returns a sorted list of the plugins which have either been stated in the
+import list or which have been added via C<< MyApp->plugin(@args); >>.
+
+If passed a given plugin name, it will report a boolean value indicating
+whether or not that plugin is loaded. A fully qualified name is required if
+the plugin name does not begin with C<Catalyst::Plugin::>.
+
+ if ($c->registered_plugins('Some::Plugin')) {
+ ...
+ }
+
+=cut
- $plugins ||= [];
- for my $plugin ( reverse @$plugins ) {
+{
+ my %PLUGINS;
+ sub registered_plugins {
+ my $proto = shift;
+ return sort keys %PLUGINS unless @_;
+ my $plugin = shift;
+ return 1 if exists $PLUGINS{$plugin};
+ return exists $PLUGINS{"Catalyst::Plugin::$plugin"};
+ }
- $plugin = "Catalyst::Plugin::$plugin";
+ sub _register_plugin {
+ my ( $proto, $plugin, $instant ) = @_;
+ my $class = ref $proto || $proto;
$plugin->require;
- if ($@) {
+ if ( my $error = $@ ) {
+ my $type = $instant ? "instant " : '';
Catalyst::Exception->throw(
- message => qq/Couldn't load plugin "$plugin", "$@"/ );
+ message => qq/Couldn't load ${type}plugin "$plugin", $error/ );
}
- {
+ $PLUGINS{$plugin} = 1;
+ unless ($instant) {
no strict 'refs';
unshift @{"$class\::ISA"}, $plugin;
}
+ return $class;
+ }
+
+ sub setup_plugins {
+ my ( $class, $plugins ) = @_;
+
+ $plugins ||= [];
+ for my $plugin ( reverse @$plugins ) {
+
+ unless ( $plugin =~ s/\A\+// ) {
+ $plugin = "Catalyst::Plugin::$plugin";
+ }
+
+ $class->_register_plugin($plugin);
+ }
}
}
{
no strict 'refs';
- my $plugins = join( ', ', sort grep { m/^Catalyst::Plugin/ } @{ $class . '::ISA' } );
+ my $plugins = join ', ', $class->registered_plugins;
$c->response->header( 'X-Catalyst-Plugins' => $plugins );
}
package TestApp;
use strict;
-use Catalyst qw/Test::Errors Test::Headers Test::Plugin/;
+use Catalyst qw/
+ Test::Errors
+ Test::Headers
+ Test::Plugin
+ +TestApp::Plugin::FullyQualified
+/;
use Catalyst::Utils;
our $VERSION = '0.01';
Catalyst::Plugin::Test::Errors
Catalyst::Plugin::Test::Headers
Catalyst::Plugin::Test::Plugin
+ TestApp::Plugin::FullyQualified
];
my $expected = join( ", ", @expected );
--- /dev/null
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::More tests => 20;
+
+use lib 't/lib';
+
+{
+
+ package Faux::Plugin;
+
+ sub new { bless {}, shift }
+ my $count = 1;
+ sub count { $count++ }
+}
+
+{
+
+ package PluginTestApp;
+ use Test::More;
+
+ use Catalyst qw(
+ Test::Plugin
+ +TestApp::Plugin::FullyQualified
+ );
+
+ sub compile_time_plugins : Local {
+ my ( $self, $c ) = @_;
+
+ isa_ok $c, 'Catalyst::Plugin::Test::Plugin';
+ isa_ok $c, 'TestApp::Plugin::FullyQualified';
+
+ can_ok $c, 'registered_plugins';
+ $c->_test_plugins;
+
+ $c->res->body("ok");
+ }
+
+ sub run_time_plugins : Local {
+ my ( $self, $c ) = @_;
+
+ $c->_test_plugins;
+ my $faux_plugin = 'Faux::Plugin';
+
+ # Trick perl into thinking the plugin is already loaded
+ $INC{'Faux/Plugin.pm'} = 1;
+
+ __PACKAGE__->plugin( faux => $faux_plugin );
+
+ isa_ok $c, 'Catalyst::Plugin::Test::Plugin';
+ isa_ok $c, 'TestApp::Plugin::FullyQualified';
+ ok !$c->isa($faux_plugin),
+ '... and it should not inherit from the instant plugin';
+ can_ok $c, 'faux';
+ is $c->faux->count, 1, '... and it should behave correctly';
+ is_deeply [ $c->registered_plugins ],
+ [
+ qw/Catalyst::Plugin::Test::Plugin
+ Faux::Plugin
+ TestApp::Plugin::FullyQualified/
+ ],
+ 'registered_plugins() should report all plugins';
+ ok $c->registered_plugins('Faux::Plugin'),
+ '... and even the specific instant plugin';
+
+ $c->res->body("ok");
+ }
+
+ sub _test_plugins {
+ my $c = shift;
+ is_deeply [ $c->registered_plugins ],
+ [
+ qw/Catalyst::Plugin::Test::Plugin
+ TestApp::Plugin::FullyQualified/
+ ],
+ '... and it should report the correct plugins';
+ ok $c->registered_plugins('Catalyst::Plugin::Test::Plugin'),
+ '... or if we have a particular plugin';
+ ok $c->registered_plugins('Test::Plugin'),
+ '... even if it is not fully qualified';
+ ok !$c->registered_plugins('No::Such::Plugin'),
+ '... and it should return false if the plugin does not exist';
+ }
+
+ __PACKAGE__->setup;
+}
+
+use Catalyst::Test qw/PluginTestApp/;
+
+ok( get("/compile_time_plugins"), "get ok" );
+ok( get("/run_time_plugins"), "get ok" );