From: Curtis "Ovid" Poe Date: Fri, 17 Feb 2006 23:18:26 +0000 (+0000) Subject: Added plugin introspection. X-Git-Tag: 5.7099_04~704 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=catagits%2FCatalyst-Runtime.git;a=commitdiff_plain;h=836e1134dfc70e064464c366a44ebb6aabfa1648 Added plugin introspection. 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::". --- diff --git a/lib/Catalyst.pm b/lib/Catalyst.pm index d93707f..a0c4d40 100644 --- a/lib/Catalyst.pm +++ b/lib/Catalyst.pm @@ -178,6 +178,14 @@ C. use Catalyst qw/My::Module/; +If your plugin starts with a name other than C, 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: @@ -534,12 +542,7 @@ loads and instantiates the given class. 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); @@ -1841,25 +1844,63 @@ Sets up plugins. =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. + + 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); + } } } diff --git a/t/lib/Catalyst/Plugin/Test/Headers.pm b/t/lib/Catalyst/Plugin/Test/Headers.pm index c5a89cb..ac47209 100644 --- a/t/lib/Catalyst/Plugin/Test/Headers.pm +++ b/t/lib/Catalyst/Plugin/Test/Headers.pm @@ -17,7 +17,7 @@ sub prepare { { 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 ); } diff --git a/t/lib/TestApp.pm b/t/lib/TestApp.pm index 8630a98..00cde9a 100644 --- a/t/lib/TestApp.pm +++ b/t/lib/TestApp.pm @@ -1,7 +1,12 @@ 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'; diff --git a/t/live_plugin_loaded.t b/t/live_plugin_loaded.t index 57a1646..36f3336 100644 --- a/t/live_plugin_loaded.t +++ b/t/live_plugin_loaded.t @@ -13,6 +13,7 @@ my @expected = qw[ Catalyst::Plugin::Test::Errors Catalyst::Plugin::Test::Headers Catalyst::Plugin::Test::Plugin + TestApp::Plugin::FullyQualified ]; my $expected = join( ", ", @expected ); diff --git a/t/unit_core_plugin.t b/t/unit_core_plugin.t new file mode 100644 index 0000000..46647fb --- /dev/null +++ b/t/unit_core_plugin.t @@ -0,0 +1,93 @@ +#!/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" );