Class-Pluggable-0.022/0000755000076600007660000000000010451206505015544 5ustar ken_devken_dev00000000000000Class-Pluggable-0.022/Changes0000755000076600007660000000041310447513064017046 0ustar ken_devken_dev00000000000000Revision history for Perl extension Class::Pluggable. 0.02 Sun Jun 25 22:56:00 2006 - added addHook, runHook, deleteHook method to Class::Pluggable. 0.01 Sat Jun 24 18:31:35 2006 - original version; created by h2xs 1.23 with options -AX -n Class::Pluggable Class-Pluggable-0.022/lib/0000755000076600007660000000000010451206505016312 5ustar ken_devken_dev00000000000000Class-Pluggable-0.022/lib/Class/0000755000076600007660000000000010451206505017357 5ustar ken_devken_dev00000000000000Class-Pluggable-0.022/lib/Class/Pluggable.pm0000755000076600007660000001263710451206370021633 0ustar ken_devken_dev00000000000000package Class::Pluggable; use 5.008006; use strict; use warnings; use vars qw($AUTOLOAD); use Carp; our $VERSION = '0.022'; sub add_plugin { my ($self, $plugin) = @_; push @{$self->_get_plugins()}, $plugin; { no strict 'refs'; s/^&//, *{"$_"} = \&{"${plugin}::$_"} foreach @{"${plugin}::EXPORT_AS_PLUGIN"}; } } sub _get_plugins { my $self = shift; if (not ref $self) { printf " !! ref = %s\n", $self; croak("Cannot handle the plugins as Class method."); } $self->{_PLUGINS} = [] if not $self->{_PLUGINS}; return $self->{_PLUGINS}; } sub get_plugins { return @{$_[0]->_get_plugins()}; } sub add_hook { my ($self, $hook, $method) = @_; if (defined ${$self->{_HOOK}}{$hook}) { carp("The hook ($hook) already in used. It will overwrite with new method."); } ${$self->{_HOOK}}{$hook} = $method; } sub run_hook { my ($self, $hook) = @_; my $method = ${$self->{_HOOK}}{$hook}; if (not defined $method) { my $caller = caller(0); croak("The hook ($hook) $caller called doesn't exists."); } $self->execute_all_plugins_method($method); } sub remove_hook { my ($self, $hook) = @_; delete ${$self->{_HOOK}}{$hook}; } sub execute_plugin_method { my ($self, $plugin, $method, @args) = @_; my $result; if (defined &{"${plugin}::$method"}) { # Give $self to make the plugin method looks like object method. { no strict 'refs'; $result = &{"${plugin}::$method"}($self, @args); } } return $result; } sub execute_all_plugins_method { my ($self, $method, @args) = @_; $self->execute_plugin_method($_, $method, @args) foreach $self->get_plugins(); } ## Deprecated Methods. sub addPlugin { carp("deprecated method."); (shift)->add_plugin(@_) } sub _getPlugins { carp("deprecated method."); (shift)->_get_plugins(@_) } sub getPlugins { carp("deprecated method."); (shift)->get_plugins(@_) } sub addHook { carp("deprecated method."); (shift)->add_hook(@_) } sub runHook { carp("deprecated method."); (shift)->run_hook(@_) } sub removeHook { carp("deprecated method."); (shift)->remove_hook(@_) } sub executePluginMethod { carp("deprecated method."); (shift)->execute_plugin_method(@_) } sub executeAllPluginsMethod { carp("deprecated method."); (shift)->execute_all_plugins_method(@_) } 1; __END__ =head1 NAME Class::Pluggable - Simple pluggable class. =head1 SYNOPSIS use Class::Pluggable; use base qw(Class::Pluggable); # Some::Plugin::Module has sub routin called newAction add_plugin("Some::Plugin::Module"); newAction(); # Plugged action. =head1 DESCRIPTION This class makes your class (sub class of Class::Pluggable) pluggable. In this documentatin, the word "pluggable" has two meanings. One is just simply adding new method to your pluggable classs from other plugin modules. So, after you plugged some modules to your class, you can use there method exactly same as your own object method. You can see this kind of plugin mechanism in CGI::Application and CGI::Application::Plugin::Session. There are one thing that Plugin developer have to know. The plugin module MUST have @EXPORT_AS_PLUGIN to use this pluggable mechanism. This works almost same as @EXPORT. But the methods in the @EXPORT_AS_PLUGIN wouldn't be exported to your package. But it would be exported to the subclass of Class::Pluggable (only when you call add_plugin()). And the another meaning of "pluggable" is so called hook-mechanism. For example, if you want to allow to other modules to do something before and/or after some action. You can do like this: $self->execute_plugin_method($_, "before_action") foreach $self->get_plugins(); ## do some your own action here. $self->execute_plugin_method($_, "after_action") foreach $self->get_plugins(); =head1 METHODS Here are all methods of Class::Pluggable. =over 4 =item add_plugin $object->add_plugin($pluginName) This will add new plugin to your class. What you added to here would be returned by get_plugins() method. =item get_plugins @plugins = $object->get_plugins(); It will return all of plugin names that are already added to YouClass. =item execute_plugin_method $result = $object->execute_plugin_method("SomePlugin", "someMethod"); This will execute the method someMethod of SomePlugin. =item execute_all_plugin_method $object->execute_all_plugin_method("someMethod"); This will execute the method someMethod of all plugin we have. This is almost same as following code. $self->execute_plugin_method($_, "someMethod") foreach $self->get_plugins(); The difference is executeAllPluginMethod can't return any values. But executePluginMethod can. =item add_hook $object->add_hook("pre-init", "pre_init"); This will add new hook to your class. Whenever run_hook("pre-init") has called, the method pre_init of all plugins which we have will be executed. =item run_hook $object->run_hook("pre-init"); This will execute the hook-method of all plugins which we have. =item remove_hook $object->remove_hook("pre-init"); This will delete the hook from YourClass. After calling this method, you cannot call run_hook("pre-init"). If you do, it will die immediately. =head1 SEE ALSO ... =head1 AUTHOR Ken Takeshige, Eken.takeshige@gmail.comE =head1 COPYRIGHT AND LICENSE Copyright (C) 2006 by Ken Takeshige This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.6 or, at your option, any later version of Perl 5 you may have available. =cut Class-Pluggable-0.022/Makefile.PL0000755000076600007660000000107010447221546017526 0ustar ken_devken_dev00000000000000use 5.008006; use ExtUtils::MakeMaker; # See lib/ExtUtils/MakeMaker.pm for details of how to influence # the contents of the Makefile that is written. WriteMakefile( NAME => 'Class::Pluggable', VERSION_FROM => 'lib/Class/Pluggable.pm', # finds $VERSION PREREQ_PM => {}, # e.g., Module::Name => 1.1 ($] >= 5.005 ? ## Add these new keywords supported since 5.005 (ABSTRACT_FROM => 'lib/Class/Pluggable.pm', # retrieve abstract from module AUTHOR => 'Ken Takeshige ') : ()), ); Class-Pluggable-0.022/MANIFEST0000755000076600007660000000023610451206471016703 0ustar ken_devken_dev00000000000000Changes Makefile.PL MANIFEST README lib/Class/Pluggable.pm t/Class-Pluggable.t META.yml Module meta-data (added by MakeMaker) Class-Pluggable-0.022/META.yml0000755000076600007660000000047310451206505017024 0ustar ken_devken_dev00000000000000# http://module-build.sourceforge.net/META-spec.html #XXXXXXX This is a prototype!!! It will change in the future!!! XXXXX# name: Class-Pluggable version: 0.022 version_from: lib/Class/Pluggable.pm installdirs: site requires: distribution_type: module generated_by: ExtUtils::MakeMaker version 6.17 Class-Pluggable-0.022/README0000755000076600007660000000664410447512736016454 0ustar ken_devken_dev00000000000000NAME Class::Pluggable - Simple pluggable class. SYNOPSIS use Class::Pluggable; use base qw(Class::Pluggable); # Some::Plugin::Module has sub routin called newAction addPlugin("Some::Plugin::Module"); newAction(); # Plugged action. DESCRIPTION This class makes your class (sub class of Class::Pluggable) pluggable. In this documentatin, the word "pluggable" has two meanings. One is just simply adding new method to your pluggable classs from other plugin modules. So, after you plugged some modules to your class, you can use there method exactly same as your own object method. You can see this kind of plugin mechanism in CGI::Application and CGI::Application::Plugin::Session. There are one thing that Plugin developer have to know. The plugin module MUST have @EXPORT_AS_PLUGIN to use this pluggable mechanism. This works almost same as @EXPORT. But the methods in the @EXPORT_AS_PLUGIN wouldn't be exported to your package. But it would be exported to the subclass of Class::Pluggable (only when you call addPlugin()). And the another meaning of "pluggable" is so called hook-mechanism. For example, if you want to allow to other modules to do something before and/or after some action. You can do like this: $self->executePluginMethod($_, "before_action") foreach $self->getPlugins(); ## do some your own action here. $self->executePluginMethod($_, "after_action") foreach $self->getPlugins(); METHODS Here are all methods of Class::Pluggable. addPlugin YourClass->addPlugin($pluginName) This will add new plugin to your class. What you added to here would be returned by getPlugins() method. getPlugins @plugins = YourClass->getPlugins(); It will return all of plugin names that are already added to YouClass. executePluginMethod $result = YourClass->executePluginMethod("SomePlugin", "someMethod"); This will execute the method someMethod of SomePlugin. executeAllPluginMethod YourClass->executeAllPluginMethod("someMethod"); This will execute the method someMethod of all plugin we have. This is almost same as following code. $self->executePluginMethod($_, "someMethod") foreach $self->getPlugins(); The difference is executeAllPluginMethod can't return any values. But executePluginMethod can. addHook YourClass->addHook("pre-init", "pre_init"); This will add new hook to your class. Whenever runHook("pre-init") has called, the method pre_init of all plugins which we have will be executed. runHook YourClass->runHook("pre-init"); This will execute the hook-method of all plugins which we have. deleteHook YourClass->deleteHook("pre-init"); This will delete the hook from YourClass. After calling this method, you cannot call runHook("pre-init"). If you do, it will die immediately. SEE ALSO ... AUTHOR Ken Takeshige, COPYRIGHT AND LICENSE Copyright (C) 2006 by Ken Takeshige This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.6 or, at your option, any later version of Perl 5 you may have available. Class-Pluggable-0.022/t/0000755000076600007660000000000010451206505016007 5ustar ken_devken_dev00000000000000Class-Pluggable-0.022/t/Class-Pluggable.t0000755000076600007660000000453110451206225021146 0ustar ken_devken_dev00000000000000######################### # change 'tests => 1' to 'tests => last_test_to_print'; use Test::More tests => 13; ######################## APlugin package APlugin; use vars qw(@EXPORT_AS_PLUGIN); @EXPORT_AS_PLUGIN = qw(&foo &bar &hoge &getHookCounter); my $hook_counter = 0; sub foo { return "foo"; } sub bar { return "bar"; } sub hoge { return "hoge"; } sub beforeAction { return "Plugin::APlugin::beforeAction"; } sub afterAction { return "Plugin::APlugin::afterAction"; } sub sampleHook { return ++$hook_counter; } sub getHookCounter { return $hook_counter; } ######################### SamplePluggable package SamplePluggable; use Class::Pluggable; use base qw(Class::Pluggable); sub new { return bless {}, shift; } sub hello { return "hello"; } ######################### main package main; BEGIN { use_ok('Class::Pluggable') }; #use APlugin; #use SamplePluggable; # Two of SamplePluggable instance shouldn't effect each other. my $sample = new SamplePluggable(); my $sample2 = new SamplePluggable(); # These are only for checking the effectivity between $sample # and $sample2. $sample2->add_plugin("APlugin"); $sample2->add_plugin("BPlugin"); is (scalar($sample->get_plugins()), 0, "initial size of plugins"); $sample->add_plugin("APlugin"); #SamplePluggable->add_plugin("APlugin"); is (scalar $sample->get_plugins(), 1, "final size of plugins"); can_ok ($sample, qw(foo bar hoge)); is ("hello", $sample->hello(), 'original method'); is ("foo", $sample->foo(), 'plugged method(foo)'); is ("bar", $sample->bar(), 'plugged method(bar)'); is ("hoge", $sample->hoge(), 'plugged method(hoge)'); is ("Plugin::APlugin::beforeAction", $sample->execute_plugin_method("APlugin", "beforeAction"), "hook test"); is ("Plugin::APlugin::afterAction", $sample->execute_plugin_method("APlugin", "afterAction"), "hook test"); ## This method doesn't exists. ## So, it should return undef. is (undef, $sample->execute_plugin_method("APlugin", "methodWhichDoesntExists"), "non-exists hook"); $sample->add_hook('hook', 'sampleHook'); $sample->run_hook('hook'); $sample->run_hook('hook'); eval { ## This should die. Because of the hook doesn't exists. $sample->run_hook('hoo2'); }; if ($@) { pass("Executing hook doesn't exists."); } else { fail("Executing hook doesn't exists."); } is ($sample->getHookCounter(), 2, "Running hook method.");